конструктор и конструктор копирования

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 ?

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

Теги:
constructor
copy-constructor

3 ответа

2

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

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

t b=5;

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

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

t b(5);

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

1

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

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

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

  • 0
    @juanchopanza Почему? Какой объект, по вашему мнению, разрушен до "привет"? Обратите внимание, что tb=5; это не назначение, это инициализация. Он использует конструктор t(int) , а не operator= .
  • 0
    Извините, неправильно прочитал ваш ответ. Я думал, что вы говорите об инициализации.
0

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

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
    ОП спрашивает, почему tb=5; не приводит к вызову деструктора, поэтому поведение не полностью ", как вы ожидали". В этой очень простой строке есть досадные тонкости :-)
  • 0
    Я полагаю, OP спрашивает, почему tb=5 не вызывает деструктор, а b=3 вызывает его. И ответ tb=5 - конструктор, а b=3 - присваивание.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню