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 выйдут из области видимости, не выполняются оба их деструктора, дважды удалив один и тот же указатель (поскольку оба они указывают на одно и то же сейчас)?
Edit:
Если я правильно понимаю Anders K, это правильный способ сделать это:
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*, а скорее a Bar* или еще что-то, может потребоваться перераспределение.
Изменить 2: Лучшим решением является идиома копирования и свопинга.