Self assignment not tested in operator

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

Описание

Сам присвоение, не протестированное в операторе, происходит, когда вы не тестируете, если аргумент к оператору присваивания копии объекта является самим объектом.

Риск

Самоприсвоение вызывает ненужное копирование. Хотя маловероятно, что вы присваиваете объект себе из-за искажения, вы или пользователи вашего класса не можете всегда обнаруживать самоприсвоение.

Самоприсвоение может вызвать тонкие ошибки, если элемент данных является указателем, и вы выделяете память динамически указателю. В вашем операторе присваивания копии вы обычно выполняете эти шаги:

  1. Освободите память, первоначально сопоставленную с указателем.

    delete ptr;
    
  2. Выделите новую память указателю. Инициализируйте новую ячейку памяти с содержимым, полученным из аргумента оператора.

     ptr = new ptrType(*(opArgument.ptr));
    

Если аргумент к оператору, opArgument, сам объект, после вашего первого шага, элемента данных указателя в аргументе оператора, opArgument.ptr, не сопоставлен с ячейкой памяти. *opArgument.ptr содержит непредсказуемые значения. Поэтому на втором шаге, вы инициализируете новую ячейку памяти с непредсказуемыми значениями.

Фиксация

Протестируйте на самоприсвоение в операторе присваивания копии вашего класса. Только после теста, выполните присвоения в операторе присваивания копии.

Примеры

развернуть все

class MyClass1 { };
class MyClass2 {
public:
    MyClass2()                : p_(new MyClass1())      { }
    MyClass2(const MyClass2& f)   : p_(new MyClass1(*f.p_)) { }
    ~MyClass2()                {
        delete p_;
    }
    MyClass2& operator= (const MyClass2& f)
    {
        delete p_;
        p_ = new MyClass1(*f.p_);
        return *this;
    }
private:
    MyClass1* p_;
};

В этом примере, операторе присваивания копии в MyClass2 не тестирует на самоприсвоение. Если параметр f текущий объект, после оператора delete p_, память, выделенная указателю f.p_ также освобожден. Поэтому оператор p_ = new MyClass1(*f.p_) инициализирует ячейку памяти что p_ точки к с непредсказуемыми значениями.

Коррекция — тестирует на самоприсвоение

Одна возможная коррекция должна протестировать на самоприсвоение в операторе присваивания копии.

class MyClass1 { };
class MyClass2 {
public:
    MyClass2()                : p_(new MyClass1())      { }
    MyClass2(const MyClass2& f)   : p_(new MyClass1(*f.p_)) { }
    ~MyClass2()                {
        delete p_;
    }
    MyClass2& operator= (const MyClass2& f)
    {
        if(&f != this) {
           delete p_;
           p_ = new MyClass1(*f.p_);
        }
        return *this;
    }
private:
    MyClass1* p_;
};

Информация о результате

Группа: Объектно-ориентированный
Язык: C++
Значение по умолчанию: 'off'
Синтаксис командной строки: MISSING_SELF_ASSIGN_TEST
Удар: носитель

Введенный в R2015b