返回类实例作为D中的指针

返回类实例作为D中的指针,d,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): Erro

我试图用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不主张的方式。还有另一个用于删除对象的回调。

只需返回
插件,它已经是一个指针


另外,只要您保留对它的引用,它就不会被GC

Plugin
Bleep
声明为类,因为您正在为
Plugin
变量分配一个新的
Bleep
,并且
Plugin
声明中没有
*
。因此,
plugin
是一个引用,而不是指针<代码>&插件
返回指向引用的指针-在本例中,该指针是一个局部变量(因此产生错误)。这根本不是你想要的。如果确实需要指针,可以显式地将
插件
转换为
void*
,但这样做有点不正常。我假设您使用的是C代码,否则就没有理由强制转换为
void*
。类对象是引用,而不是指针,如果可能的话应该保持这样。如果您要将其传递给C代码(可能稍后会调用您的D代码,因为C不知道如何处理D类),那么您或多或少会被困在使用
void*
的过程中,但我建议您避免使用其他方法

只要您的D代码有对该对象的引用,GC就不会释放该对象,但是如果您将其传递给C函数,并且在D代码中不保留对该对象的任何引用,GC将在某个时候收集该对象

如果要自己显式释放对象,那么不要使用GC
delete
被安排为弃用,通常您不应该自己释放GC堆上的内容。这是总司令的工作。您可以对对象调用
destroy
来销毁它(例如
destroy(obj);
),但内存不会被释放(而是调用析构函数,对象的vtable将被调零,因此使用它将导致segfault)

如果你真的想自己分配和释放一个对象,那么你应该使用
malloc
free
,尽管这肯定更复杂。您必须使用
malloc
分配一块与对象大小相同的内存,然后使用在该内存块中构造类以创建对象。然后要释放它,必须显式调用它的析构函数,然后在该内存上调用
free
。自定义分配器的工作正在进行中,这肯定会使这更容易(可能会使它更接近
alloc.new!MyClass(args)
alloc.free(obj)
),但它们还没有完成,因此还没有在标准库中


如果不需要确定性销毁,使用GC处理分配和释放对象的一种方法是在D代码中保留对对象的引用,然后在想要释放对象时将该引用设置为
null
。在GC决定收集它之前,它不会释放它,但它会使GC在你使用它之前不会收集它,这样一旦你使用它,它就可以收集它。

插件
不是指针。这是推荐信。当一个新的
Bleep
被分配给
Plugin
时,
Plugin
Bleep
显然是类,因此
Plugin
变量是一个参考。如果
Plugin
是一个结构,并且他正在实例化一个新的
Plugin
,那么结果将是一个
Plugin*
,然后那将是一个指针,但因为它是一个类,所以它是一个引用。@JonathanMDavis在D中,类引用是一个指针,隐式转换为
void*
,不,它不是。引用类似于指针,但它不同,类型系统对它们的处理也不同(例如,引用是多态的,指针不是多态的-即使你有一个指向类的指针)。@JonathanMDavis尚未使用D(我们正在讨论的语言)对象引用被实现为一个简单的指针,指向对象在内存中的位置。实际上,它在引擎盖下如何实现并不重要。该语言将它们视为不同且不兼容的类型。不能将引用分配给指针,反之亦然。如果您声明
Plugin*
并且
Plugin
是一个类,那么您声明的是指向
插件
引用的指针,而不是指向
插件
的指针。事实上,它本质上是一个指针,这意味着显式转换到和从
void*
中转换应该可以工作,但隐式转换到和从
void*
中转换不会工作,并且类型系统根本不会将指针和引用视为相同的。感谢您详细的回答。首先,我将尝试正常的实例化和GC.addRoot(cast(void*)插件)。