我看了this presentation,在幻灯片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 ++编译)
现在,我理解为什么构造函数会以坏样式调用两次,但为什么析构函数会这样做呢?
答案 0 :(得分:8)
X(int v) { a = v; }
// ^^^^^
带下划线的行是作业。没有operator=
需要int
(v
),但是从int
到A
的隐式转换。因此,构造A
类型的临时对象并将其传递给编译器为您生成的赋值运算符。它会在以后被破坏(在完全表达它之后创建它)并且你有第二个析构函数你没想到。
答案 1 :(得分:1)
逻辑是
Instantiate a Class ... +1 [Constuctor]
Desinstantiate a Class ... -1 [Destructor]
当该对象超出范围或被明确删除时,将为类对象调用析构函数。
所以你可以期望类的Destructors被调用这些类的次数相同。
答案 2 :(得分:1)
你成了“隐性类型转换”的受害者。尝试向构造函数添加“explicit”,并查看代码中的错误(它将停止在前一个隐式转换的位置进行编译):
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
答案 3 :(得分:0)
<强>简介强>
在执行构造函数和执行时,还有一件事需要考虑。 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 ++切换到另一种语言,这一点很重要,因为可能处理不同。