如何创建对象复制

时间:2017-03-30 14:53:01

标签: c++

现在我正在处理两个.cpp文件中的两个函数。假设我正在使用名为someStruct的结构:

struct someStruct {
  int num;
}

A.cpp:

int main() {
  someStruct *a = NULL;
  bool ret;
  ret = foo(a);
  std::cout << a->num; // should print 5
}

B.cpp:

bool foo(someStruct *a) {
  someStruct *b = someFunction(); // points to an instance of someStruct on the stack
  // note that b->num should hold 5

  // need something here
  // ATTEMPT 1:
  a = new someStruct(*b);
  // ATTEMPT 2
  a = (someStruct *)malloc(sizeof(someStruct));
  a = memcpy(a, b, sizeof(someStruct));
}

我想要完成的是主函数中的a最终指向someStruct的实例,该实例与{{1}中的结构指针b具有相同的值}}

我列出的所有尝试都没有奏效。

1 个答案:

答案 0 :(得分:0)

术语:HEAP vs STACK

您的问题应命名为“如何创建对象副本”。原因之一是原始对象位置无关紧要,从堆栈上的对象和堆上的对象创建副本几乎是相同的。第二个原因是您当前的代码尝试复制由someFunction()返回值指向的对象,这可能仅在堆上someFucntion()创建对象时才有意义。否则,如果someFunction()在堆栈上创建了这样的对象:

someStruct tmp;
tmp.num = 5; 
return &tmp;

然后一旦someFunction()完成执行,它的堆栈帧就会被释放,并且可能会被重用于其他函数堆栈。因此'tmp'结构位于内存中,可以随时覆盖,因此您不能依赖其数据。在局部变量超出范围之后,切勿使用指向局部变量的指针。

复制对象

好吧,你的 ATTEMPT 1 很好。使用new创建类或结构调用构造函数来构建对象。您传递了另一个对象作为参数,因此调用了复制构造函数。您没有编写复制构造函数,但编译器自动创建了一个简单的复制构造函数,因此它正确地将所有字段从原始对象复制到新创建的。

但是,由于程序另一部分中的错误,cout未显示预期输出。调用foo(a);表示将a的副本作为参数传递给foo。因此,您不要在main中更改a的{​​{1}}值,而是更改foo foo副本的值。返回主页后,a仍然是a,无法取消引用。作为最小修复,您需要通过指针或引用传递NULL(已经是指针,因此有点混乱),而不是通过值传递它。例如:

a

最好为每个动态分配的缓冲区调用int main() { someStruct *a = NULL; bool ret; ret = foo(&a); std::cout << a->num; // should print 5 delete a; return ret; } bool foo(someStruct **x) { someStruct *b = someFunction(); // points to an instance of someStruct on the heap *x = new someStruct(*b); delete b; return true; }; ,在较大的程序中,内存泄漏可能会变得非常痛苦。