为什么代码调用析构函数两次
why code calls destructor twice?
我看了一下这个演示文稿,在幻灯片 379 中,它显示了以下代码(有一些小的更改):
#include <iostream>
using namespace std;
struct A
{
A() { cout << "A()" << endl; }
A(int v) { cout << "A(int)" << endl; }
~A() { cout << "~A()" << endl; }
};
struct X
{
X(int v) { a = v; }
X(long v) : a(v) {}
A a;
};
int main()
{
cout << "bad style:" << endl;
{ X slow(int(2)); }
cout << "good style:" << endl;
{ X fast(long(2)); }
}
输出为:
bad style:
A()
A(int)
~A()
~A()
good style:
A(int)
~A()
(这段代码是在我的机器上运行的,用 G++ 编译)
现在,我明白了为什么构造函数会在糟糕的样式中被调用两次,但是析构函数为什么要这样做呢?
X(int v) { a = v; }
// ^^^^^
带下划线的行是一个赋值。没有需要int
(v
)的operator=
,但有一个从int
到A
的隐式转换。因此,将构造一个类型 A
的临时对象,并将其传递给编译器为您生成的赋值运算符。它稍后被销毁(在完整表达式之后,它是在结尾中创建的),并且还有您没想到的第二个析构函数。
逻辑是
Instantiate a Class ... +1 [Constuctor]
Desinstantiate a Class ... -1 [Destructor]
当类对象超出范围或被显式删除时,将为该对象调用析构函数。
因此,您可以预期类的析构函数将被调用相同的创建次数。
你成了"隐式类型转换"的受害者。尝试将"显式"添加到构造函数中,并查看代码中的问题(它将在前一个隐式转换的位置停止编译):
struct A
{
explicit A() { cout << "A()" << endl; }
explicit A(int v) { cout << "A(int)" << endl; }
~A() { cout << "~A()" << endl; }
};
以下是解释:http://en.cppreference.com/w/cpp/language/implicit_cast
简介
在C++中执行构造函数和析构函数时,还有一件事需要考虑。
您声明的是静态分配对象还是动态分配对象?
静态分配
#include <iostream>
using namespace std;
class A {
public:
// constructors
A() { cout << "A()" << endl; }
A(int v) { cout << "A(int)" << endl; }
// destructors
~A() { cout << "~A()" << endl; }
};
class X {
public:
// constructors
X(int v) { a = v; }
X(long v) : a(v) {}
// variables
A a;
};
int main()
{
cout << "bad style:" << endl;
X slow(int(2));
cout << "good style:" << endl;
X fast(long(2));
}
动态分配
#include <iostream>
using namespace std;
class A {
public:
// constructors
A() { cout << "A()" << endl; }
A(int v) { cout << "A(int)" << endl; }
// destructors
~A() { cout << "~A()" << endl; }
};
class X {
public:
// constructors
X(int v) { a = new(v); }
X(long v) : { a = new(); *a = v; }
// destructors
~X() { delete a; }
// variables
A* a;
};
int main()
{
cout << "bad style:" << endl;
X slow = new X(int(2));
cout << "good style:" << endl;
X fast = new (long(2));
// do something else with "X"
delete slow();
delete fast();
}
总结
静态分配变量自动调用析构函数,而使用指针的动态分配变量则需要显式调用析构函数。
**额外**
如果您以前使用过另一种面向对象语言,或者必须从C++切换到另一种,那么考虑这一点很重要,因为处理方式可能不同。
相关文章:
- g++的分段错误(在NaN上使用to_string两次时)
- 蛇在C++不会连续转两次
- 计算两个代码块的时间复杂度
- 检查一个数组是否包含在另一个数组中,以相反的顺序,至少两次
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 这两个代码片段相似,但显示的结果不同
- 如何使用预处理器指令包含两次具有不同代码的文件?
- 为什么在下面的代码中调用复制构造函数两次
- 相同的代码执行两次:性能差异
- *char数组到字符串(两次运行代码和两个不同的结果)
- 为什么我的代码两次收到此错误"undefined reference to `Pizza::Pizza()' "
- Cmake并需要两次运行才能成功构建代码
- 为什么在此代码代码段中将复制构造函数两次称为两次
- 为什么我的代码两次打印相同的命令行参数
- 在此C 代码示例中发生了两次复制构造函数的调用
- 给定以下代码(在GCC 4.3中),为什么两次转换为引用
- 由于难以理解的原因,我的代码被写了两次
- 为什么代码调用析构函数两次
- 为什么我的代码要求"请输入 2-12 之间的数字:"两次?
- 不知道为什么代码被计算两次