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: Лучшим решением является идиома копирования и свопинга.