C ++返回本地对象

时间:2011-06-14 22:25:03

标签: c++

我和几位同事正在讨论当从C ++方法返回局部变量(在堆栈上分配)时会发生什么。

以下代码适用于单元测试,但我认为这只是因为单元测试很幸运,并且不会尝试重用obj使用的堆栈上的内存。

这有效吗?

static MyObject createMyObject() {
    MyObject obj;
    return obj;
}

8 个答案:

答案 0 :(得分:23)

会发生复制构造函数被调用以生成本地对象的副本,这就是调用者收到的内容。

编译器可能会在名为copy elision的进程中删除副本,但这完全取决于编译器 - 您无法对其进行太多控制。

此模式能够产生您担心的问题,但前提是您将指针引用返回到本地对象。

答案 1 :(得分:4)

创建

obj,然后使用对象的复制构造函数将其复制出方法/函数。

您可以通过声明obj来使static不在堆栈中。返回该对象也会返回一个副本,但每次调用该函数时都不会创建该对象。然后,您可以将对象作为参考返回:

static MyObject & createMyObject() {
    static MyObject obj;
    return obj;
}

(此处没有复制,obj只创建一次,其地址在运行时保持不变。)

答案 2 :(得分:1)

按值返回对象,因此将调用它的复制构造函数,并返回原始对象的COPY并将其存储在调用者的堆栈中。如果此方法返回局部变量的指针(或引用),它将失败。

答案 3 :(得分:1)

返回MyObject的副本。如果MyObject具有正确复制所有内容的复制构造函数,那么这应该没问题。请注意,它可能有一个复制构造函数,即使没有明确列出一个 - 编译器定义的默认复制构造函数(成员分配所有内容)可能适用于您的目的。

答案 4 :(得分:1)

在此示例中,MyObject按值返回。这意味着它的副本被制作并传递回调用函数。 (在某些情况下the compiler can optimize the spurious copy away,但仅限于在MyObject上调用复制构造函数并将副本放在堆栈上时。)

答案 5 :(得分:1)

假设其他所有人都错过了这个问题的明显混淆来源 - static

您没有声明在MyObject中创建的createMyObject实例具有静态存储持续时间;相反,您将函数createMyObject声明为具有内部链接。

答案 6 :(得分:1)

函数“返回本地对象”是可以的,因为编译器会将函数转换为真正返回值。相反,它将接受一个引用 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);

但是,如果您返回指向本地对象的引用或指针,编译器将无法完成转换。您将返回一个指向已销毁对象的引用或指针。

答案 7 :(得分:0)

这很好用。它将创建一个返回MyObject的临时匿名变量:

Anonymous variables and objects

binding a temporary object to a reference to const