struct Foo { Foo(int i) { ptr = new int(i); } ~Foo() { delete ptr; } int* ptr; }; int main() { { Foo a(8); Foo b(7); a = b; } //Do other stuff }
Если я правильно понимаю, компилятор автоматически создаст функцию-член оператора присваивания для
Foo
. Однако это просто берет значениеptr
вb
и помещает его вa
. Память, выделеннаяa
, изначально кажется потерянной. Я мог бы сделать вызовa.~Foo();
перед выполнением присваивания, но я где-то слышал, что вам редко нужно явно вызывать деструктор. Допустим, вместо этого я пишу оператор присваивания дляFoo
, который удаляет указательint
левого операнда перед присвоением r-значения l-значению. Вот так:Foo& operator=(const Foo& other) { //To handle self-assignment: if (this != &other) { delete this->ptr; this->ptr = other.ptr; } return *this; }
Но если я это сделаю, то когда
Foo a
иFoo b
выйдут за пределы области видимости, не запустятся оба их деструктора, дважды удалив один и тот же указатель ( так как они оба указывают на одно и то же сейчас)?Редактировать:
Если я правильно понял Андерса К., это правильный способ сделать это:
Foo& operator=(const Foo& other) { //To handle self-assignment: if (this != &other) { delete this->ptr; //Clones the int this->ptr = new int(*other.ptr); } return *this; }
Теперь
a
клонировалint
, чтоb
указал и устанавливает на него собственный указатель. Возможно, в этой ситуацииdelete
иnew
не нужны, потому что они просто включаютint
s, но если член данных не былint*
а скорееБар*
или еще что-то, может потребоваться перераспределение.Редактировать 2: Лучшим решением представляется идиома копирования и замены.