【发布时间】:2014-11-29 08:21:45
【问题描述】:
问题
析构函数在以下代码中被调用了两次:
class Foo
{
public:
~Foo()
{
std::cout << "Destructor called\n";
}
Foo& operator=(const Foo& other)
{
std::cout << "Assignment called\n";
return *this;
}
};
Foo foo()
{
return Foo();
}
int main()
{
foo();
return 0;
}
输出:
Destructor called
Destructor called
我怀疑这是由于对赋值运算符或复制构造函数的一些隐式调用。我不知道是否调用了复制构造函数,因为添加任何类型的构造函数都会神奇地解决问题(如下所述),但至少不会调用赋值运算符。
如前所述,如果我添加一个构造函数,问题就会消失:
class Foo
{
public:
Foo()
{
std::cout << "Constructor called\n";
}
Foo(const Foo& other)
{
std::cout << "Copy constructor called\n";
}
~Foo()
{
std::cout << "Destructor called\n";
}
Foo& operator=(const Foo& other)
{
std::cout << "Assignment called\n";
return *this;
}
};
输出变为:
Constructor called
Destructor called
如果我返回引用而不是对象,问题也会消失(但会导致“本地或临时变量的返回地址”警告):
Foo& foo()
{
return Foo();
}
问题
为什么析构函数被调用两次,为什么在使用默认构造函数时行为不同?是否有合乎逻辑的解释,或者编译器是否有错误?
如果有什么不同的话,我正在使用 MSVC 2013。
【问题讨论】:
-
您忘记包含复制构造函数。并在Release构建中测试代码,以便返回值优化可以避免额外的复制。
-
赋值运算符应该返回非常量引用。
-
析构函数调用次数取决于构造函数调用次数,这取决于优化,即编译器和选项。
-
你怎么知道第一个例子没有调用拷贝构造函数?
标签: c++ constructor language-lawyer destructor