使用malloc()初始化类

7

当从C malloc保留内存时,应如何使用c++类?

我正在使用一个C库(lua),我需要将一个C++类暴露给它,以便在这种情况下进行垃圾回收并预留空间,lua进行内存分配。

以下是一个更简单的相似场景:

#include <string>

class Clase{
private:
    std::string valor;
public:
    Clase(){}
    Clase(const std::string & valor) : valor(valor){}
    const std::string & get() const { return this->valor; }
    void set(const std::string & valor){ this->valor = valor;}
    ~Clase(){}
};

typedef struct
{
    Clase cls;
}Estructura;

int main(int argc, char ** argv)
{
    Estructura * est = (Estructura *) malloc(sizeof(Estructura));

    est->cls.set("Hola");   // First attempt

    Clase myCls;   // Second attempt
    est->cls = myCls;

    return 0;
}

我理解并检查了,使用malloc函数创建类实例时不会调用类构造函数;这是预期的,因此不能使用无效实例(Class中的字符串)调用复制(分配)运算符。我怀疑第二次尝试在复制Class实例中的字符串时失败了。

那么:

  • 是否可以正确地初始化通过malloc函数保留内存的类实例?
  • 还有哪些注意事项?虚函数表?
  • 与malloc函数对应的free函数是否会导致内存泄漏?(我猜想由于类析构函数不会被调用,所以字符串不会被正确释放?[我假设字符串保存在实例本身之外的内存中])

在Estructura中使用Clase的指针可以很好地工作,这是最佳解决方案吗?

额外提问:什么是在lua垃圾回收时删除实例的最佳方法?使用__gc元方法还是有其他更好的方法?


2
https://dev59.com/uXVC5IYBdhLWcg3wpi98#222578 - tynn
最好的解决方案可能是编写一个中间层包装器来将C接口到C++。开始定义一个C++函数,位于类外部,使用new来初始化类并返回创建对象的指针。然后为公共方法创建包装器。 - LPs
你为什么有'Estructura'这个包装器?(顺便说一句,你的代码中没有指针。) - Peter - Reinstate Monica
请仅返回翻译文本:(我的意思是,不要在“Estructura”内部使用指针。) - Peter - Reinstate Monica
是的,最初我希望在结构体内部有Clase实例,而不是一个指针,这样当结构体被删除(或其内存被释放)时,实例也会被删除。那个包装器存在是因为它将来可能会有更多的字段。 - Javier Mr
1个回答

15

使用 malloc 而不是 new 有点奇怪,但是这是可能的。你需要使用定位 new:

void *memory = malloc(sizeof(Estructura));

Estructura *est = new(memory)Estructura;

当你完成一个对象使用时,你需要自己调用它的析构函数:

est->~Estructura();

所有内容,例如虚函数表(vtables)等,都会正确初始化,所以不必担心。棘手的部分在于处理删除操作,因为您需要在通过free释放内存之前析构对象。delete会自动为您执行此操作,但您需要自己做这个。


1
测试过并且工作得很好。之前不知道有放置 new 的方法。谢谢。 - Javier Mr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接