use*_*486 2 c++ constructor destructor
我正在尝试确定C++函数是否安全返回具有构造函数和析构函数的对象.我对标准的理解是它应该是可能的,但我用简单的例子进行的测试表明它可能有问题.例如以下程序:
#include <iostream>
using namespace std;
struct My
{ My() { cout << "My constructor " << endl; }
~My() { cout << "My destructor " << endl; }
};
My function() { My my; cout << "My function" << endl; return my; }
int main()
{ My my = function();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出输出:
My constructor
My function
My destructor
My destructor
Run Code Online (Sandbox Code Playgroud)
在MSVC++上编译时,但使用gcc编译时会得到以下输出:
My constructor
My function
My destructor
Run Code Online (Sandbox Code Playgroud)
这是"未定义的行为"的情况,还是一个不按标准方式运行的编译器?如果是后者,哪个?gcc输出更接近我的预期.
到目前为止,我一直在设计我的类,假设每个构造函数调用最多只有一个析构函数调用,但是这个例子似乎表明这个假设并不总是成立,并且可能依赖于编译器.标准中是否有任何内容指定此处应该发生什么,或者最好避免函数返回非平凡对象?如果这个问题是重复的,请道歉.
在这两种情况下,编译器都会为您生成一个复制构造函数,它没有输出,因此您不知道它是否被调用:请参阅此问题.
在第一种情况下,使用编译器生成的复制构造函数,它与第二个析构函数调用匹配.该行return my;调用复制构造函数,为其提供my用于构造返回值的变量.这不会产生任何输出.
my然后被摧毁.函数调用完成后,返回值将在行尾消失{ function();.
在第二种情况下,完全省略了返回的副本(允许编译器作为优化执行此操作).你只有一个My实例.(是的,即使它改变了程序的可观察行为,也可以这样做!)
这些都没关系.虽然作为一般规则,如果你定义自己的构造函数和析构函数,你还应该定义自己的复制构造函数(和赋值运算符,如果你有c ++ 11,可能会移动构造函数和移动赋值).
尝试添加自己的复制构造函数,看看你得到了什么.就像是
My (const My& otherMy) { cout << "My copy constructor\n"; }
Run Code Online (Sandbox Code Playgroud)