2012-06-04 3 views
4

Выполняя мои назначения программирования, я, кажется, спотыкаюсь о базовых концепциях C++. Я нашел ошибку в моей программе, и это было вызвано тем, что мой деструктор работает больше раз, чем я ожидал. Вот пример кода, демонстрирующий, что я делаю неправильно, вплоть до простых вещей.C++: Почему мой деструктор работает дважды?

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    A(int num) 
    { 
     number = num; 
     cout << "A constructed with number " << number << ".\n"; 
    } 
    ~A() 
    { 
     cout << "A destructed with number " << number << ".\n"; 
    } 
private: 
    int number; 
}; 

class B 
{ 
public: 
    B(A pa) 
     : a(pa) 
    { 
     cout << "B constructor run.\n"; 
    } 
    ~B() 
    { 
     cout << "B destructor run.\n"; 
    } 
private: 
    A a; 
}; 


int main() 
{ 
    A foo(7); 
    { 
     B bar(foo); 
    } 
    //Pause the program. 
    system("pause"); 
} 

Что я ожидаю, так это A foo(7); выделяет пространство в стеке для объекта с A именем foo и вызовите конструктор, передавая 7. Он присваивает 7 значение number и выводит результат, указывающий, что побежал конструктор. Теперь B bar(foo); выделяет пространство в стеке для объекта B с именем bar и вызывает конструктор, передавая foo по значению, которое является просто контейнером для int. Конструктор присваивает передаваемому ему параметру A его собственному частному элементу данных a и выводит вывод на экран.

Теперь, когда bar выходит из области видимости на закрывающей фигурной скобкой, я ожидаю bar «s деструктор будет называться, который печатает вывод на экран, а затем вызывает деструктор для своих членов данных, а именно A a. Этот деструктор выводит вывод на экран и отбрасывает int number, который он содержал.

Что я ожидаю, что вывод должен быть:

A constructed with number 7. 
B constructor run. 
B destructor run. 
A destructed with number 7. 
//Destructors should be called in the reverse order of their construction right? 

Фактический выход:

A constructed with number 7. 
B constructor run. 
A destructed with number 7. //This is unexpected. 
B destructor run. 
A destructed with number 7. 

Что является причиной, что дополнительное разрушения?

+3

Создайте шумоподобные конструкторы. –

+0

Проверьте [Правило трех] (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – rlduffy

+0

Возможный дубликат [Почему деструктор класса называется дважды?] (HTTP: // StackOverflow.com/questions/2627540/why-is-the-destructor-of-the-the-class-called-two) –

ответ

1

Очевидно, что он исходит из данных элемента A a; класса B. Я предполагаю, что вы сомневаетесь в том, что почему бы не увидеть какой-либо вывод конструкции из A, потому что он сконструирован по умолчанию для copy-ctor для класса A. Лучше добавить один экземпляр-ctor для класса A, чтобы вы увидели конструкцию процедура.

A(const A& a) 
{ 
    number = a.number; 
    cout << "A copy-constructed with number " << number << ".\n"; 
} 
0

, потому что в классе B есть один член A a , чтобы разрушить объект B, сначала вызвать деструктор его члена.

1

Ненавижу это, когда люди получают симпатичные «foo» и «bar».

Но я вижу два экземпляра «A», которые строятся - одно явно, другое - неявно «B». И вызваны два деструктора.

Что не нравится в этой картине;)?

2

Вашего B конструктор принимает A объекта по значению, что означает, что foo копируется в параметр pa который затем получает скопированный к члену a. Компилятор смог лишить одну из копий (аргумент конструктору), но другой не может быть удален, и у вас есть второй объект A, который будет уничтожен.