Действительно ли безопасно не проверять в операторе copy assignemt, присваивается ли объект самому себе?

Вот пример реализации "Правила трех", который я нашел:

class Array { 
    public: 
        int size; 
        int* vals;
        Array() : size(0), vals(NULL){}
        Array( int s, int* v );
        Array(const Array&); // 1
        Array& operator=(const Array&); // 2
        ~Array(); // 3
}; 

Array::~Array() { 
   delete []vals; 
   vals = NULL; 
} 

Array::Array( int s, int* v ){
    size = s; 
    vals = new int[size]; 
    std::copy( v, v + size, vals ); 
} 

Array::Array(const Array& rhs):
    size(rhs.size),
        vals((rhs.size) ? new int[size] : NULL)
{
    if(size)
        std::copy(rhs.vals, rhs.vals + rhs.size, vals);
}

Array& Array::operator=(const Array& rhs){
//  if(this == &rhs) // no need
//      return *this;
    int* a = (rhs.size)? new int[rhs.size] : NULL; // this is why we don't need the above check: if this line throws then vals is untouched. if this is ok (local variable) then continue (next won't throw).
    std::copy(rhs.vals, rhs.vals + rhs.size, a); // copying to a even (self assignment won't harm)
    delete[] vals;
    vals = a;
    size = rhs.size;

    return *this;
}

Как вы можете видеть выше, проверка в Операторе Копирования удаляется как факт создания локальной переменной, затем удаляет указатель члена и присваивает ему локальный. Но что имеет значение для меня, если я напишу:

int main() {
   int vals[ 4 ] = { 11, 22, 33, 44 };  
   Array a1( 4, vals ); 

   a1 = a1; // here I assigned a1 to itself

    return 0;
}

Я назначил a1 для себя это значит a1"s valsудаляется, а затем назначается локальный a в операторе копирования? Это правильный путь? Есть ли в моем коде некоторые подводные камни?

  • Любой совет, совет высоко ценится.

1 ответ

Решение

Оператор назначения копирования будет функционировать в том смысле, что самоопределение будет иметь ожидаемое поведение: содержимое значения массива будет неизменным.

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

Имеет ли это значение для производительности... это будет сильно зависеть от факторов, зависящих от использования. В конце концов, это только проблема, если вы выполняете самокопирование. Как часто ты это делаешь? И если вы действительно не делаете это так часто (или когда-либо), тогда тест - это просто условная ветвь, которая вам не нужна.

В то же время рассмотрим определение vector, Это имеет очень специфические обстоятельства, когда итераторы / указатели / ссылки в vector стать недействительным. И копирование vector не один из них. Так что, если расположение хранилища объектов является частью интерфейса вашего типа массива (так оно и есть для vector), то самостоятельное копирование имеет более широкие последствия для вашего интерфейса.

Другие вопросы по тегам