我和几个同事正在就当一个局部变量(在栈上分配)从C++方法返回时会发生什么进行辩论。
以下代码可以通过单元测试,但我认为这只是因为该单元测试幸运地没有尝试重用obj使用的栈上内存。
这是否可行?
static MyObject createMyObject() {
MyObject obj;
return obj;
}
我和几个同事正在就当一个局部变量(在栈上分配)从C++方法返回时会发生什么进行辩论。
以下代码可以通过单元测试,但我认为这只是因为该单元测试幸运地没有尝试重用obj使用的栈上内存。
这是否可行?
static MyObject createMyObject() {
MyObject obj;
return obj;
}
MyClass *obj = new MyClass();
在函数内部创建一个本地对象,返回对象指针,并且该方法的签名是MyClass * myMethod(){...}
,如果我像这样调用它MyClass *retObj = myMethod();
,然后解引用它像这样retObject->someMethod();
,它总是有效的。这是应该的吗,还是我运气好? - SexyBeastnew
来创建并返回指针,因此对象不会被复制,而是会继续存在,直到您 delete
指针。当您返回指向 本地 对象的指针时,而不是使用 new
创建的对象时,就会遇到问题。 - Mark Ransomnew
在堆上创建对象,该对象会继续存在,无论调用和退出哪个函数,而不使用它则在栈上创建对象,该对象仅限于函数本地,并且不能保证在函数退出后仍然存在。 - SexyBeast创建了obj
,然后使用对象的复制构造函数从方法/函数中复制出它。
您可以通过将其声明为static
来使此obj
不在堆栈中。返回对象也会返回一个副本,但对象不会在每次调用函数时被创建。然后,您可以将该对象作为引用返回:
static MyObject & createMyObject() {
static MyObject obj;
return obj;
}
这里不允许复制,同时obj
只被创建一次,在运行时其地址保持不变。
函数“返回本地对象”是可以的,因为编译器会将函数转换为实际上不返回值。相反,它将接受一个引用MyObject& __result
,并使用将分配返回值即obj
的本地对象来复制构造__result
。在您的情况下,函数将被重写为:
static void createMyObject(MyObject& __result) {
MyObject obj;
// .. process obj
// compiler generated invocation of copy constructor
__result.MyObject::Myobject( obj );
return;
}
每次调用createMyObject
都会被转换为将引用绑定到现有对象的形式。例如,下面这种调用:
MyObject a = createMyObject();
将被转换为:
MyObject a; // no default constructor called here
createMyObject(a);
但是,如果你返回一个指向局部对象的引用或指针,编译器无法完成转换。你将会返回一个指向已经销毁的对象的引用或指针。
MyObject
(因为你只是返回一个_副本_)没有什么不同--即MyObject x = createMyObject();
与更高效的MyObject x;
达到了相同的效果。 - Kerrek SB