为什么在 C++ 中按值返回对象时不调用析构函数?[复制]

Why is the destructor not called when returning an object by value from a function in C++? [duplicate]

提问人:Elhazin 提问时间:5/3/2023 更新时间:5/3/2023 访问量:77

问:

我有一个定义析构函数的 C++ 类,并且我通过函数的值返回此类的对象。但是,我注意到函数返回时没有调用析构函数。相反,只有当对象在 main 函数结束时超出范围时,才会调用它。此外,我注意到,当我在函数调用前后打印对象中变量的地址时,地址保持不变。

下面是演示该问题的代码的简化版本:

#include <iostream>

class MyClass {
public:
    int i;
    
    MyClass() {
        std::cout << "Constructing MyClass object" << std::endl;
    }
    
    ~MyClass() {
        std::cout << "Destructing MyClass object" << std::endl;
    }
};

MyClass createObject() {
    MyClass obj;
    obj.i = 42;
    std::printf("Address of i inside createObject: %p\n", &obj.i);
    return obj;
}

int main() {
    MyClass newObj = createObject();
    std::printf("Address of i inside main: %p\n", &newObj.i);
    return 0;
}

当我运行这个程序时,输出是:

Constructing MyClass object
Address of i inside createObject: 0x7fff54c8a15c
Address of i inside main: 0x7fff54c8a15c
Destructing MyClass object

我期望在 createObject() 返回时调用析构函数,但这似乎没有发生。谁能解释为什么会这样,以及我如何确保在按函数的值返回对象时调用析构函数?另外,为什么对象中变量 i 的地址在从函数返回后没有改变?

C++ 对象 内存 构造函数 堆栈

评论

1赞 john 5/3/2023
不需要析构函数,因为您正在返回 .这称为返回值优化 (RVO)。程序中只有一个对象,该对象在 中正确销毁。这也是地址不变的原因。objMyClassmaini
1赞 Artyer 5/3/2023
这是NRVO。要抑制它,.return std::move(obj);
1赞 user4581301 5/3/2023
或者查阅编译器文档,了解禁用 RVO 的选项。
2赞 Avi Berger 5/3/2023
另请参阅此处
1赞 user4581301 5/3/2023
旁注:这是允许优化器更改程序的可观察行为的罕见情况之一。有关详细信息,请参阅 As-if 规则复制省略

答: 暂无答案