2015-07-20 3 views
0

Рассмотрите следующий фрагмент C++ и вывод под ним.Почему деструктор IMPLICITLY называется дважды на одном объекте?

#include <iostream> 
using namespace std; 

class One { 
public: 
    One(int num); 
    One(); 
    ~One(); 
private: 
    int number; 
}; 

One::One(int num) { 
    number = num; 
    cout << "One constructor number = " << number << endl; 
} 

One::One() { 
    number = 0; 
    cout << "default One constructor\n"; 
} 

One::~One() { 
    cout << "One destructor. number = " << number << endl; 
    number = 0; 
} 

int main() { 
    One uno; 
    uno = One(2); 
    return 0; 
} 

по умолчанию Один конструктор

Один номер конструктор = 2

один деструктор. номер = 2

Один деструктор. number = 2

Обратите внимание на репликацию последней строки. Я понимаю (& ненавижу), почему конструктор по умолчанию вызывается первой строкой в ​​главном, но деструктор для этого экземпляра никогда не вызывается. Вместо этого деструктор для второго экземпляра неявно называется дважды. Зачем? И как переменная «число» может сохраняться при номере = 2? Деструктор установил значение 0. Это похоже на сборщик мусора, который пытается удалить экземпляр, созданный конструктором по умолчанию, но попав в старую копию второго. Это тривиальный пример, но это настоящая проблема, когда приходит время удалять указатели.

+0

Самое простое решение не использовать сырые указатели на право собственности. И если вы хотите увидеть, какой объект разрушен, напечатайте 'this', а не некоторый элемент данных, который копируется при создании экземпляров класса. Наконец, на C++ нет сборщика мусора. Деструкторы запускаются в конце области действия объекта и после этого очищается память объекта. – chris

+2

Вы создали два объекта «Один». Обе они разрушаются индивидуально. 'uno'' number' был изменен, потому что вы назначили ему новое значение (2), поэтому теперь оно печатает то же сообщение, что и деконструктор временного объекта. И C++ не имеет сборщика мусора, FYI. – Cornstalks

+0

Что значит не использовать необработанные указатели для владения (есть ли приготовленные указатели, которые лучше подходят для владения) – apchar

ответ

6
One uno; // Create a default One instance - default constructor called. 
uno = One(2); // Create a temporary One instance - number constructor called and prints 2. 
       // Assign temporary to uno - uno now has the number 2. 
       // Destroy temporary One instance - destructor called and prints 2. 
return 0; 
// uno destroyed. It has the number 2, so this also prints 2. 

Или, с точки зрения выхода вы увидели:

default One constructor // from uno construction 
One constructor number = 2 // from temporary One(2) construction 
One destructor. number = 2 // from temporary One(2) destruction 
One destructor. number = 2 // from uno destruction (since number has changed) 
+0

Но если временному объекту присваивается значение uno, то почему значение uno's number равно 0, когда временный объект уничтожены? число = 0 находится в деструкторе. – apchar

+0

Временное уничтожается после назначения копии, а не раньше. Таким образом, значение числа копируется из временного объекта до его установки на ноль. – nneonneo

+0

Итак, «назначьте», вы имеете в виду копию? Не так, как ссылка присваивается переменной. – apchar

Смежные вопросы