2012-03-31 62 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