使用malloc()时如何实现复制构造函数

时间:2014-07-14 13:02:37

标签: c++ malloc copy-constructor

创建Foo的实例时,将传递对象oMyClass并调用其复制构造函数。 MyClass有一个void指针作为成员,指向在dtor中释放的内存。 如何在同一内存中调用free()两次时,如何正确实现复制构造函数以避免分段错误?

这是我的代码:

int main(int argc, char* argv[])
{
    MyClass oMyClass();

    Foo oFoo(oMyClass);
} 

class MyClass
{
    public:
         MyClass()
         {
          struct foo *pFoo;
          buf = malloc(sizeof(*pFoo));
         }

         MyClass::MyClass(const MyClass& oMyClass)
         {
            printf("Copyconstructor called\n");
            //?
         }
         MyClass::~MyClass()
         {
          struct foo *pFoo = (struct foo *)buf;
          free(pFoo);
         }

    private:
      void* buf;

    };


/*Foo.h*/

class Foo
{
public:
    Foo( MyClass& oMyClass);
    Foo();
    ~Foo();
private:
    MyClass m_oMyClass;
};

/*Foo.cpp*/
Foo::Foo( MyClass& oMyClass): m_oMyClass(oMyClass)
{

}

Foo::Foo()
{
}

4 个答案:

答案 0 :(得分:4)

根本不要写一个复制构造函数(参见Rule of Zero)。

相反,依靠带有自定义删除程序的智能指针为您执行资源管理。 unique_ptr将为您提供可移动的所有权,shared_ptr将为您提供共享所有权:

void* data = malloc(sizeof(*pFoo));
// either
std::unique_ptr<void, void(*)(void*)> foo(data, free);
// or
std::shared_ptr<void> foo(data, free);

只有当你真的想要执行所附数据的深层复制时,你才需要编写一个复制构造函数(但在这种情况下你仍然可以free执行const unique_ptr

答案 1 :(得分:1)

你必须复制数据(或保留一个引用计数,只有在引用它的最后一个对象被销毁时才释放数据 - 但如果数据是可变的,这几乎肯定不是你想要的那样。)

MyClass::MyClass(const MyClass& oMyClass)
{
    buf = malloc(sizeof(foo));

    memcpy(buf, oMyClass.buf, sizeof(foo));
    // or new(buf) foo(*reinterpret_cast<foo*>(oMyClass.buf));
}

如果您使用普通new / delete代替malloc / free,则可以免费获得foo的副本构造函数。 ..

答案 2 :(得分:1)

当您在此处复制构造时,您需要创建自己的构造项目的方式。

“默认”是简单地将项目复制到新项目。这就是为你提供seg-fault的原因,因为当正常复制时,指向foo的指针在两个地方都是相同的。然后,当破坏时,你释放两次相同的记忆。

因此,在复制构造函数中,您需要分配新内存,并复制内存的内容:

MyClass::MyClass(const MyClass& oMyClass)
{
    buf = malloc(sizeof(foo));
    memcpy(buf, oMyClass.foo, sizeof(foo));            
    printf("Copyconstructor called\n");
    //?
}

答案 3 :(得分:1)

问题就在这里 - 你想要发生什么?

您可以共享两个类之间的内存,也可以复制内存。

共享内存

理想情况下,使用std::shared_ptrboost::shared_ptr这样的类会自动为您执行引用计数。如果您想自己进行引用计数,则必须使用编译器中可用的原子内在函数,并使用整数malloced来跟踪引用计数。

复制内存

您可以使用std::memcpy将内存复制到新分配的内存中:

MyClass::MyClass(const MyClass& other)
    : buf(malloc(sizeof(*buf)) {
  if (!buf) {
    throw std:bad_alloc();
  }
  std::memcpy(buf, other.buf, sizeof(*buf));
}