更新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
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
对于那些好奇的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
Run Code Online (Sandbox Code Playgroud)
问题:
// 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
Run Code Online (Sandbox Code Playgroud)
// 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;
}
Run Code Online (Sandbox Code Playgroud)
// 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;
}
Run Code Online (Sandbox Code Playgroud)
使用以下方法编制GCC:
g++ -c Add.cpp -o Add.o ; g++ -c Main.cpp -o Main.o ; g++ Add.o Main.o -o test
Run Code Online (Sandbox Code Playgroud)
似乎 C++ 标准对于何时必须调用函数参数析构函数可能有点含糊。C++03和C++11都在5.2.2/4“函数调用”中说(添加了强调):
当定义参数的函数返回时,参数的生命周期结束。每个参数的初始化和销毁都发生在调用函数的上下文中。
因此,参数的析构函数在概念上不会出现在函数的右大括号处。这是我不知道的事情。
该标准给出了一个注释,解释了这意味着如果参数的析构函数抛出,则仅考虑调用函数或“更高层”的异常处理程序(具体来说,即使被调用函数具有“函数尝试块”,不予考虑)。
虽然我认为其目的是为了 MSVC 行为,但我可以看到有人会如何解释允许 GCC 行为的读数。
话又说回来,也许这是 GCC 中的一个错误?