现在我正在处理两个.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
具有相同的值}}
我列出的所有尝试都没有奏效。
答案 0 :(得分:0)
您的问题应命名为“如何创建对象副本”。原因之一是原始对象位置无关紧要,从堆栈上的对象和堆上的对象创建副本几乎是相同的。第二个原因是您当前的代码尝试复制由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;
};
,在较大的程序中,内存泄漏可能会变得非常痛苦。