堆栈上的 C++ 变量似乎没有在函数作用域的末尾被释放

标签 c++ scope

我编写了以下简短代码来进行实验,并尝试获得有关何时调用对象的构造函数和析构函数的“第一手”经验:

class Foo
{
public:
    Foo(int bar)
    {
        this->bar = bar;
        std::cout << "Standard constructor called" << std::endl;
    }
    ~Foo()
    {
        std::cout << "Standard destructor called" << std::endl;
    }
    Foo(const Foo &foo)
    {
        std::cout << "Copy constructor called" << std::endl;
        this->bar = foo.bar;
    }
    inline int get_bar() { return bar; }
private:
    int bar;
};

Foo make_foo(int bar)
{
    Foo f1(bar);
    std::cout << "About to return foo with address of: " << &f1 << std::endl;
    return f1;
}

int main()
{
    Foo f2 = make_foo(3);
    std::cout << "New variable has address of: " << &f2 << std::endl;
    std::cout << "And a value of " << f2.get_bar() << std::endl;
}

但是当我运行这段代码时,我发现有些奇怪的事情发生了。正如预期的那样,打印了“调用的标准构造函数”,并打印了该函数中 foo 的地址。但是当函数结束时,没有调用析构函数,并且 f2 实际上具有与 f1 相同的内存地址,尽管根据我的理解,f1 应该超出范围并释放其内存,因为它在堆栈上,对吧?或者这不是这种情况下的预期结果?

我的期望是调用复制构造函数将 f1 复制到 f2,然后 f1 将调用其析构函数,而 f2 将占用不同的内存地址。

如果有人好奇,这是实际输出:

Standard constructor called                                                                          
About to return new foo with address of: 0x7fff518e5a88                                              
New variable has address of: 0x7fff518e5a88                                                          
And a value of 3                                                                                     
Standard destructor called     

有趣的是,当我将 make_foo 的返回类型更改为引用类型时,该函数的执行几乎和我预期的一样,f1 被破坏,f2 复制垃圾数据。

这是某种特定情况吗?堆栈上的变量在返回以分配给另一个我应该注意的变量时不会释放其内存?

最佳答案

编译器正在执行返回值优化 (RVO)。你可以在这里读到它: https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization

关于堆栈上的 C++ 变量似乎没有在函数作用域的末尾被释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50779429/

相关文章:

linux - 在 Bash 中,为什么 `x=100 echo $x` 不打印任何内容?

javascript - 从成员函数对对象所做的更改不会持续存在。范围/引用问题?

c++ - 将 C/C++ 变量放入未命名范围的原因?

c++ - 用3D+2D图形重绘QGLWidget

c++ - 当 img(roi) 未返回正确值时如何正确提取 ROI

c++ - C++ 的可执行场景 (BDD)

javascript - setInterval 函数中的变量增量器

javascript - 比较 Javascript 范围

c++ - qt编程中未初始化的switchcase错误

c++ - 递归创建 boost 属性树