Действительно ли безопасно не проверять в операторе copy assignemt, присваивается ли объект самому себе? - PullRequest
0 голосов
/ 11 декабря 2018

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

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 'vals удаляется, а затем назначается локальный a в назначении копированияоператор?Это правильный путь?Есть ли в моем коде некоторые подводные камни?

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

1 Ответ

0 голосов
/ 11 декабря 2018

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

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

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

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

...