【问题标题】:Initialization of Class using malloc()使用 malloc() 初始化类
【发布时间】:2015-07-14 20:00:42
【问题描述】:

当 C++ 类的内存已从 C malloc 中保留时,应该如何使用它?

我正在使用一个 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 保留其内存的类实例?
  • 还有哪些其他注意事项?vtables?
  • 对 malloc 的免费补充会导致内存泄漏吗? (我猜由于不会调用 Clase 析构函数,字符串不会被正确释放?[我假设字符串在实例本身之外保存内存])

在 Estructura 中为 Clase 使用指针,效果很好,这是最好的解决方案吗?

作为奖励,在 lua 垃圾收集实例时删除实例的最佳方法是使用 __gc 元方法还是更好的方法?

【问题讨论】:

  • 最好的解决方案可能是编写一个中级包装器来接口 C 到 C++。开始在类之外定义一个 C++ 函数,该函数使用 new 来初始化类并返回所创建对象的指针。公共方法的创建包装器。
  • 为什么有Estructura 包装器? (顺便说一句,您的代码中没有指针。)
  • (我的意思是,Estructura 里面没有 ponter。)
  • 是的,最初我希望将 Clase 实例放在结构中,而不是指针,因此当结构被删除(或释放内存)时,实例也会被删除。那个包装器在那里是因为将来可能有更多的字段。

标签: c++ c lua malloc new-operator


【解决方案1】:

使用malloc 代替new 有点奇怪,但这是可能的。你需要使用placement new:

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

Estructura *est = new(memory)Estructura;

当您完成对象后,您有责任自己调用析构函数:

est->~Estructura();

所有东西,比如 vtables,都会被正确初始化,所以不用担心。尴尬的一点是处理删除,因为您需要在通过free 释放内存之前破坏对象。 delete 会自动为您执行此操作,但您需要自己执行此操作。

【讨论】:

  • 经过测试,效果很好。不知道安置新。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多