Member 12914219 Ответов: 3

Почему деструктор вызывается оператором = функцией


даже несмотря на то, что я передаю рефренированный аргумент t = оператору, что такое разрушитель разрушения......
результат выглядит следующим образом
привет
мир
-------
= вызывается оператор
des называется //для чего нужен этот деструктор
привет
дес называется
дес называется

Что я уже пробовал:

#include <iostream>
#include<string.h>

using namespace std;
class strin{
    int len;
    char *ptr;
    public:

    strin(){len=0;ptr=NULL;}
    strin(   const char  *s)
    {
          len=strlen(s);
         ptr=new char[len+1];
         strcpy(ptr,s);
    }
    strin( const strin &A)
    {
        len=A.len;
        ptr=new char[len+1];
        strcpy(ptr,A.ptr);
        cout<<"cpy cnst is called\n";

    }
    void print(void)
    {
        cout<<ptr<<"\n";
    }


    strin operator + ( const strin  &obj )
    {
     strin temp;
     temp.len=len+obj.len;
      temp.ptr=new char[temp.len+1];
     strcpy(temp.ptr,ptr);
     strcat(temp.ptr,obj.ptr);
     cout<<"+ is called \n";
     return temp;
    }
~strin()
{
    delete[]ptr;
    cout<<"des is called\n";
}
strin operator = (const strin &x)
{
    len=x.len;
    ptr=new char[len+1];
    strcpy(ptr,x.ptr);
    cout<<"= operator is called\n";

}
};

int main()
{


  strin x("hello");
  strin y("world");
  x.print();
  y.print();

  cout<<"--------\n";

  y=x;
  y.print();

  }

0x01AA

Я думаю, что вам нужно сначала исправить ваш Operator= подпись, а также возвращаемое значение.

const strin& operator=(const strin &rhs)

John R. Shaw

Возвращаемый тип не должен быть const.
T& T::operator=(const T&)

0x01AA

Спасибо за этот намек. Я никогда об этом не думал. Но есть ли у него недостаток, чтобы вернуть const?
Заранее спасибо.

John R. Shaw

Возвращение 'const' нарушает нормальное поведение.
a = b = c; // 'const' или нет 'const' это работает
(a = b) = c; // является законным, но не будет работать, если оператор присваивания возвращает 'const'
Именно поэтому оператор присваивания по умолчанию задается стандартом для возврата 'T&' вместо 'const T&'.

0x01AA

Большое Вам за это спасибо! С уважением.

3 Ответов

Рейтинг:
28

0x01AA

Это происходит потому, что, скорее всего, ваше возвращаемое значение (по значению) войдет в нирвану и будет уничтожено ... сомнительный...

Это и есть правильная реализация Operator= который также не будет вызывать деструктор:

const strin& operator = (const strin &x)
{
    cout<<"= operator is called\n";
    if (this != &x)
    {
       // TODO: In case ptr allready has Memory allocated, one Need to release it 
       //       first. 
       // 

       // Assign
       len=x.len;
       ptr=new char[len+1];
       strcpy(ptr, x.ptr);
    }
    return(*this);
}

Внимание, возможна утечка памяти
Вышесказанное все еще не совсем верно. Вам также нужно сначала проверить, есть ли this имеет уже выделенную память и освобождает ее в первую очередь на всякий случай. Это будет вашим упражнением


Боковое замечание, мой личный предпочтительный способ, как я сочетаю operator= и конструктор копирования

конструктор копирования
MyClass::MyClass (const MyClass &rhs)
	: InitMember_1(),
          .....
	  InitMember_N()
{
	operator= (rhs);
}

б) оператор=
const MyClass& MyClass::operator=(const MyClass &rhs)
{
   if (this != &rhs)
   {
     // TODO: Implement 
   }
   return(*this);
}


CPallini

Проверка личности - это хороший момент. Мой 5.
Я думаю, что правильная реализация также должна удалить ранее выделенную память (если таковая имеется).
Простите за педантичность.

0x01AA

Я добавил эту утечку памяти в то же самое время, когда вы написали свой комментарий :)
Спасибо вам за ваши 5.

Member 12914219

какова цель возвращения (*this);.

0x01AA

Это позволяет некоторым нравится (что лично мне не нравится):
a= b= c;

Предполагая, что вы определяете свой оператор= следующим образом void operator = (const strin &x) вы не можете цеплять назначения.

CPallini

Он находится в подписи оператора
https://en.cppreference.com/w/cpp/language/copy_assignment
Обоснование показано, например, на этой странице
http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

Maciej Los

5ed!

0x01AA

Большое вам спасибо Мацей

0x01AA

Большое спасибо, что согласились. Надеюсь, это действительно помогло. Кстати. Продолжайте свои испытания, это хороший способ учиться.

Рейтинг:
1

Maciej Los

5ed!

CPallini

Спасибо!

Рейтинг:
1

John R. Shaw

Следующие примеры дают сильную гарантию, к которой вы должны стремиться.
Вы должны использовать assert(this != &rhs) чтобы поймать ошибки самоназначения во время разработки. Есть только две причины для проверки самоназначения: (1) избегать ненужных распределений, (2) объект предназначен для хранения больших объемов данных.

// Add swap to your class
// swap is one of your best friends
// because it is guaranteed not to throw.
void swap(strin& x) noexcept
{
	using std::swap;
	swap(len, x.len);
	swpa(ptr, x.ptr);
}

// Version 1
// This version behaves the same in all cases,
// even on the rare occasion you do self assignment
strin& operator=(const strin& rhs)
{
	cout << "= operator is called" << endl;
	// Using a constructor here provides the strong
	// guarantee that this object will not be modified
	// if an exception is thrown.
	strin temp(rhs);
	swap (*this, temp);
    return(*this);
}

// Version 2
// The difference between this and version 1
// is that temporary object is built on the stack
// when the operator is called.
strin& operator=(strin rhs)
{
	cout << "= operator is called" << endl;
	swap (*this, rhs);
    return(*this);
}

// Version 3
// Basically the same as version 1
strin& operator=(const strin& rhs)
{
	cout << "= operator is called" << endl;
	// first use temporaries in case an exception is thrown.
	char temp_ptr = new char [rhs.len+1];
	strcpy(temp_ptr, rhs.ptr);
	
	// No exception were thrown, so we can modify this.
	delete [] ptr;
	ptr = temp_ptr;
	len = rhs.len;
	
    return(*this);
}


Maciej Los

5ed!