2013-10-26 71 views
1

我已经采取了看看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 ++编译)

现在,我明白了为什么构造函数会在坏风格中调用两次,但为什么析构函数会这样做呢?

+1

好,如果构造函数被调用两次,这意味着有两个对象要销毁。 – GManNickG

+0

如果构造函数被调用两次,则构造两个对象。所以需要销毁两个物体。 – juanchopanza

回答

8
X(int v) { a = v; } 
//   ^^^^^ 

带下划线的行是一个赋值。没有operator=需要intv),但存在从intA的隐式转换。因此,构造一个A类型的临时对象并将其传递给编译器为您生成的赋值运算符。它在后来被破坏(在完成表达式被创建之后),并且还有你没有想到的第二个析构函数。

+1

我不知道任务可以调用构造函数... o_O – 0x499602D2

1

的逻辑是

Instantiate a Class ... +1 [Constuctor] 
Desinstantiate a Class ... -1 [Destructor] 

当该对象流出的范围或显式地删除析构函数被称为一类对象。

所以你可以期望这些类的析构函数被称为这些类被创建的次数相等。

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(); 
} 

摘要

静态分配的变量自动调用析构函数,而动态分配的变量,美se指针,你需要显式调用析构函数。

** **外

如果您以前使用另一种面向对象的语言,或是从C++切换到另一个,这个考虑,因为也许不同的处理是很重要的。

1

你是“隐式类型转换”的受害者。尝试“明确的”添加到您的构造函数和会看到什么是错在你的代码(将在前者的隐式转换的地方停止编译):

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

相关问题