2013-10-07 5 views
0
#include <iostream> 

using namespace std; 

class t{ 
private: 
int * arr; 

public: 
    t() { arr=new int[1]; arr[0]=1;} 
    t(int x) {arr=new int[1]; arr[0]=x;} 
    t(const t &); 
    ~t() {cout<<arr[0]<<" de"<<endl; delete [] arr;} 
    t & operator=(const t & t1){arr[0]=t1.arr[0];return *this;} 
    void print(){cout<<arr[0]<<endl;} 

}; 
t::t(const t & t1) {arr=new int[1];arr[0]=t1.arr[0];} 

int main(){ 

    t b=5; 
    cout<<"hello"<<endl; 
    b.print(); 
    b=3; 
    b.print(); 
    return 0; 
} 

Почему результатконструктор и конструктор копирования

hello 
5 
3 de 
3 
3 de ? 

почему "т Ь = 5;" не вызовет деструктор? как работает «t b = 5»? он создает временный объект (класса t), используя сначала конструктор «t (int x)», затем используйте конструктор копирования «t (const t &)», чтобы создать b? Если это так, то почему он не вызывает дескриптор для временного объекта?

ответ

1

Поскольку вы не оператор присваивания принимая int, b = 3; интерпретируется как

`b.operator=(t(3));` 

Это создает временный t экземпляр, и уничтожает его после возврата назначения. Вот что печатает первую линию de. Наконец, в конце main, b выходит за пределы области действия, его деструктор вызывается и печатает вторую строку.

+0

@juanchopanza Почему? Какой объект, по вашему мнению, уничтожен до «привет»? Обратите внимание, что 't b = 5;' is ** not ** присваивание, это инициализация. Он использует конструктор 't (int)', а не 'operator ='. –

+0

Извините, неправильно прочитайте свой ответ. Я думал, вы говорили об инициализации. – juanchopanza

0

Может быть, немного след от вашей программы поможет вам понять, что happing:

int main(){ 
    t b=5; // as you expected, this call the constructor of your object. 
    cout<<"hello"<<endl; 
    b.print(); // as you could see, this call print() and print 5 
    b=3; // this is where the confusion begins. You didn't provide a way 
     // from your object to make an assigment from an integer, but you 
     // provide a way to construct an object from integer. So, your 
     // compiler will construct a temporary object, with 3 as parameter 
     // and use this object to do this assignment. Once this is a 
     // temporary object, it will be destructed at the end of this 
     // operation. That is why you are getting the message: 3 de 
    b.print(); // print 3 as expected 
    return 0; // call the destruct from the object that was assigned before 
} 
+0

OP спрашивает, почему 't b = 5;' is * not *, что приводит к вызову деструктора, поэтому поведение не полностью «как вы ожидали». В этой очень простой строке есть раздражающие тонкости :-) – juanchopanza

+0

Я думаю, OP спрашивает, почему 't b = 5' не вызывает деструктор, а' b = 3' вызывает его. И ответ заключается в том, что 't b = 5' является конструктором, а' b = 3' - назначением. – Amadeus

+0

См. Мой ответ. 't b = 5;' требуется конструктор копирования, но копии конструкций * могут * быть отменены (и чаще всего). Но при реализации, не являющейся верной, или если вы отключите копирование на своем компиляторе, вы * увидите * копию копии и вызов деструктора. – juanchopanza

2

почему "т Ь = 5;" не вызовет деструктор?

Когда вы сделаете это:

t b=5; 

вы получаете copy initialization. Семантически вызывается конструктор неявного преобразования t(int), а затем создается экземпляр t(const t&) для создания экземпляра b. Однако компилятор разрешен до elide the copy, что и происходит в вашем случае. Объект построен на месте, без необходимости создания копии. Вот почему вы не видите деструкторный вызов. Но вашему классу по-прежнему нужен конструктор копирования для компиляции этого кода: copy elision не является обязательным и не зависит от того, будет ли компилятор компилятора выполнять эликсирование или нет.

Если бы вы сказали

t b(5); 

тогда было бы прямой инициализации, без копирования элизии, и только с одним вызова конструктора. Для компиляции для вашего класса не потребуется конструктор копирования.

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