2012-03-31 61 views
3

我試圖編譯下面的代碼在d返回一個類實例的指針d

void* instantiate(_LV2_Descriptor* descriptor, 
    double sample_rate, char * bundle_path, 
    LV2_Feature** features) { 
    Plugin plugin = new Bleep(sample_rate, features); 
    return &plugin; 
} 

,但我得到以下錯誤

../src/lv2/plugin.d(38): Error: escaping reference to local plugin 

什麼是創建一個正確的方式類實例並將其作爲指針返回?也是以這樣的方式,它沒有被GC聲明。對象刪除有另一個回調。

回答

4

PluginBleep顯然是因爲你班」重新分配一個新的BleepPlugin變量,plugin的聲明沒有*。所以,plugin是一個參考,而不是一個指針。 &plugin正在返回一個指向參考的指針 - 在這種情況下,它是一個局部變量(因此是錯誤)。這不是你想要的。如果你真的想要一個指針,你可以明確地投pluginvoid*,但是有點不正常的事情。我假設,你是與C代碼接口,否則真的不應該有一個理由去void*。類對象是引用,而不是指針,如果可能的話應該保留。如果你將它傳遞給C代碼(可能稍後會調用你的D代碼,因爲C不知道如何處理D類),那麼你或多或少的使用void*,但我會建議避免它,否則。

只要您的D代碼有引用它,GC就不會釋放該對象,但是如果您將它傳遞給C函數,並且不在D代碼中留下任何引用,則它將會使用由GC在某一時刻收集到

如果你打算明確地釋放對象,那麼不要使用GC。 delete計劃棄用,並且您通常不應該自行釋放GC堆中的內容。這是GC的工作。你可以在一個對象上調用destroy來銷燬它(例如destroy(obj);),但是內存不會被釋放(而是析構函數會被調用,並且對象的vtable將被清零,以便使用它將導致段錯誤)。

如果你真的想自己分配和釋放一個對象,那麼你應該使用mallocfree,儘管這肯定更復雜。您必須分配與malloc對象大小的內存塊,然後使用std.conv.emplace構建該塊內存中的類以創建該對象。然後釋放它,你必須明確地調用它的析構函數,然後在該內存上調用free。工作正在進行自定義分配器,這應該使這更容易(可能使它更接近alloc.new!MyClass(args)alloc.free(obj)),但它們還沒有完成,所以還沒有在標準庫中。

如果您不需要確定性破壞,則使用GC處理分配和釋放對象的一種方法是簡單地在D代碼中保留對該對象的引用,然後在想要釋放時將該引用設置爲null物體。在GC決定收集它之前,它不會釋放它,但它會使GC在你完成之前不會收集它,並且一旦你完成就可以收集它。

+0

感謝您的精心解答。我將首先嚐試普通實例化和GC.addRoot(cast(void *)插件)。 – 2012-04-01 17:42:55

1

剛剛返回plugin這已經是一個指針

也只要你保持對它的引用,也不會被GC聲稱

+2

'plugin'不是一個指針。這是一個參考。當一個新的'Bleep'被分配給'Plugin','Plugin'和'Bleep'顯然是類,所以'Plugin'變量是一個引用。如果'Plugin'是一個結構體,並且他正在實例化一個新的'Plugin',那麼結果將是一個'Plugin *',然後_that_將是一個指針,但由於它是一個類,所以它是一個引用。 – 2012-03-31 20:23:41

+0

@JonathanMDavis D類引用是一個指針,可以隱式轉換爲void *' – 2012-03-31 21:41:09

+0

不,不是。一個引用類似於一個指針,但它不是一樣的,類型系統不會對它們進行相同的處理(例如引用是多態的,指針不是 - 即使你有一個指向類的指針)。 – 2012-03-31 21:46:09