C++:在对象范围之外调用析构函数?

标签 c++ destructor

更新 1: 添加了建议的打印“this”。

更新 2:拆分成几个文件以尝试阻止 gcc 优化。

更新 3:记录复制构造函数并输入添加函数。

更新 4: 添加了 Clang 的输出和 main 中的第二个 cout。

我希望参数析构函数在函数的最后语句中被调用。从今以后,我希望从下面的代码中得到以下输出。

default constructor: 008DFCF8
other constructor: 008DFCEC
copy constructor: 008DFBC0
in member add
destroying: 008DFBC0
copy constructor: 008DFBB8
copy constructor: 008DFBB4
in function add
destroying: 008DFBB4
destroying: 008DFBB8
3 == 3
end of main
destroying: 008DFCEC
destroying: 008DFCF8

使用 MSVC (Visual Studio) 时,输出符合预期。但是 GCC (4.8.2-19ubuntu1) 输出以下内容,表明函数参数的析构函数在 main() 中的第一个 cout 语句之后但在最后一个语句之前被调用。

default constructor: 0x7fff2fcea510
other constructor: 0x7fff2fcea520
copy constructor: 0x7fff2fcea550
in member add
copy constructor: 0x7fff2fcea540
copy constructor: 0x7fff2fcea530
in function add
3 == 3
destroying: 0x7fff2fcea530
destroying: 0x7fff2fcea540
destroying: 0x7fff2fcea550
end of main
destroying: 0x7fff2fcea520
destroying: 0x7fff2fcea510

对于那些好奇 clang++ (3.4-1ubuntu3) 输出什么的人。

default constructor: 0x7fff52cf9878
other constructor: 0x7fff52cf9870
copy constructor: 0x7fff52cf9860
copy constructor: 0x7fff52cf9858
in function add
3 == copy constructor: 0x7fff52cf9850
in member add
3
destroying: 0x7fff52cf9850
destroying: 0x7fff52cf9858
destroying: 0x7fff52cf9860
end of main
destroying: 0x7fff52cf9870
destroying: 0x7fff52cf9878

问题:

  1. 我最初的怀疑是 GCC 正在内联函数?如果这是真的,是否有办法禁用此优化?
  2. C++ 规范中的哪一部分允许在 main 中的 cout 之后调用析构函数?特别令人感兴趣的是有关内联的规则(如果相关)以及何时安排析构函数。

// Test.h
#ifndef __TEST_H__

#include <iostream>

using namespace std;

class Test
{
public:
    int val;

    Test(Test const &a) : val(a.val)
    {
        cout << "copy constructor: " << this << endl;
    }

    Test() : val(1)
    {
        cout << "default constructor: " << this << endl;
    }

    Test(int val) : val(val)
    {
        cout << "other constructor: " << this << endl;
    }

    ~Test()
    {
        cout << "destroying: " << this << endl;
    }

    int add(Test b);
};

#endif

// Add.cpp
#include "Test.h"

int Test::add(Test b)
{
    cout << "in member add" << endl;
    return val + b.val;
}

int add(Test a, Test b)
{
    cout << "in function add" << endl;
    return a.val + b.val;
}

// Main.cpp
#include "Test.h"

int add(Test a, Test b);

int main()
{
    Test one, two(2);

    cout << add(one, two) << " == " << one.add(two) << endl;

    cout << "end of main" << endl;

    return 0;
}

为 GCC 编译使用:

g++ -c Add.cpp -o Add.o ; g++ -c Main.cpp -o Main.o ; g++ Add.o Main.o -o test

最佳答案

对于何时必须调用函数参数析构函数,C++ 标准似乎有点模棱两可。 C++03和C++11都在5.2.2/4“函数调用”中说(强调):

The lifetime of a parameter ends when the function in which it is defined returns. The initialization and destruction of each parameter occurs within the context of the calling function.

因此参数的析构函数在概念上不会出现在函数的右大括号中。这是我不知道的事。

该标准给出了一个说明,解释了这意味着如果参数的析构函数抛出异常,则仅考虑调用函数或“更高”的异常处理程序(具体来说,即使被调用函数具有“函数尝试-” block ',不考虑)。

虽然我认为意图是针对 MSVC 行为,但我可以看到有人可能如何解释允许 GCC 行为的读数。

话说回来,也许这是 GCC 中的错误?

关于C++:在对象范围之外调用析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26249588/

相关文章:

c++ - 程序似乎泄漏内存,但未检测到内存泄漏

python - 为什么 Python 在销毁对象之前销毁类变量?

kotlin - Kotlin 编程语言中的析构函数

c++ - 使用 Sphinx-apidoc 从 C++ 代码生成文档

c++ - 我如何惯用地将 BOOL 转换为 boolean 值?

c++ - 在另一个静态对象的析构函数中构造的静态对象的析构函数

c++ - 一个离开析构函数的有效异常案例

c++ - 显式调用析构函数

c++ - 进程终止,但其网络资源仍然存在

c++ - 通过 TCP 发送图片