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++
По умолчанию: On для рукописного кода, off для сгенерированного кода
Синтаксис командной строки: MISSING_SELF_ASSIGN_TEST
Влияние: Средний
Введенный в R2015b