Рубрики

Когда мы должны написать наш собственный оператор присваивания в C ++?

Ответ такой же, как и в конструкторе копирования. Если класс не содержит указателей, тогда нет необходимости писать оператор присваивания и конструктор копирования. Компилятор создает конструктор копирования по умолчанию и операторы присваивания для каждого класса. Созданный компилятором конструктор копирования и оператор присваивания могут оказаться недостаточными, когда у нас есть указатели или какое-либо распределение ресурсов во время выполнения, например, дескриптор файла, сетевое соединение и т. Д. Например, рассмотрим следующую программу.

#include<iostream>

using namespace std;

  
// Класс без определенного пользователем оператора присваивания

class Test

{

    int *ptr;

public:

    Test (int i = 0)      { ptr = new int(i); }

    void setValue (int i) { *ptr = i; }

    void print()          { cout << *ptr << endl; }

};

  

int main()

{

    Test t1(5);

    Test t2;

    t2 = t1;

    t1.setValue(10);

    t2.print();

    return 0;

}

Выход вышеуказанной программы — «10». Если мы посмотрим на main (), мы изменили 't1', используя функцию setValue (), но изменения также отражаются в объекте 't2'. Этот тип неожиданных изменений вызывает проблемы.
Поскольку в указанной выше программе не определен пользовательский оператор присваивания, компилятор создает оператор присваивания по умолчанию, который копирует «ptr» с правой стороны на левую. Так что оба 'ptr начинают указывать на одно и то же место.

Мы можем справиться с вышеуказанной проблемой двумя способами.

1) Не допускайте присвоения одного объекта другому объекту. Мы можем создать свой собственный фиктивный оператор присваивания и сделать его приватным.

2) Напишите свой собственный оператор присваивания, который делает глубокое копирование.

То же самое верно и для конструктора копий.

Ниже приведен пример перегрузки оператора присваивания для вышеуказанного класса.

#include<iostream>

using namespace std;

  

class Test

{

    int *ptr;

public:

    Test (int i = 0)      { ptr = new int(i); }

    void setValue (int i) { *ptr = i; }

    void print()          { cout << *ptr << endl; }

    Test & operator = (const Test &t);

};

  

Test & Test::operator = (const Test &t)

{

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

   if(this != &t)

     *ptr = *(t.ptr);

  

   return *this;

}

  

int main()

{

    Test t1(5);

    Test t2;

    t2 = t1;

    t1.setValue(10);

    t2.print();

    return 0;

}

Выход

5

Мы также должны добавить конструктор копирования в вышеприведенный класс, чтобы операторы типа «Test t3 = t4;» также не вызывали никаких проблем.

Обратите внимание на условие if в операторе присваивания. При перегрузке оператора присваивания мы должны проверять самопредставление. В противном случае присвоение объекта себе может привести к неожиданным результатам (см. Это ). Самопроверка проверки не обязательна для указанного выше класса «Test», потому что «ptr» всегда указывает на одно целое число, и мы можем повторно использовать одну и ту же память. Но в целом, это рекомендуемая практика, чтобы сделать проверку самоназначения.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Когда мы должны написать наш собственный оператор присваивания в C ++?

0.00 (0%) 0 votes