Действительно ли безопасно не проверять в операторе 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
), то самостоятельное копирование имеет более широкие последствия для вашего интерфейса.