C++返回本地对象

C++ return local object

本文关键字:对象 返回 C++      更新时间:2023-10-16

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

以下代码适用于单元测试,但我相信这只是因为单元测试很幸运,并且没有尝试重用obj.使用的堆栈上的内存

这样行吗

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

发生的情况是,复制构造函数被调用以生成本地对象的副本,而这正是调用者接收到的。

编译器可能会在一个称为副本省略的过程中消除副本,但这取决于编译器——你对它没有太多控制权

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

创建

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

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

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

(此处没有副本,而且obj只创建一次,并且其地址在运行时保持不变)。

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

返回MyObject的副本。如果MyObject有一个可以正确复制所有内容的复制构造函数,这应该是可以的。请注意,它可能有一个复制构造函数,即使没有明确列出一个——编译器定义的默认复制构造函数(按成员分配所有内容)可能对您的目的很好。

在本例中,MyObject是按值返回的。这意味着它将被复制并传递回调用函数。(在某些情况下,编译器可以优化伪造的副本,但只有当这相当于在MyObject上调用副本构造函数并将副本放在堆栈上时。)

假设其他人只是错过了这个问题中一个明显的困惑来源——static:

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

函数可以"返回本地对象";,因为编译器会将函数转换为,而不是真正返回值。相反,它将接受引用MyObject& __result,并使用将被分配返回值的本地对象(即obj)来复制构造__result。在您的情况下,函数将被重写为:

static void createMyObject(MyObject& __result) {
    MyObject obj;
    // .. process obj
    // compiler generated invocation of copy constructor
    __result.MyObject::Myobject( obj );
    return;
}

并且CCD_ 12的每次调用也将被转换以将引用绑定到现有对象。例如,调用以下表单:

MyObject a = createMyObject();

将转换为:

MyObject a;  // no default constructor called here
createMyObject(a);

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

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

匿名变量和对象

将临时对象绑定到对const 的引用