Сбросить объект
В последнее время я часто сбрасываю объект, назначая ему новое значение с помощью operator=
, Большинство моих занятий имеют copy constructor
а также operator=
определяется с помощью идиомы "копировать и менять". Что отлично работает в большинстве случаев, хотя и не так эффективно, как могло бы быть, но в большинстве случаев это не имеет значения. Есть один случай, когда это не работает. Это когда destructor
должен быть вызван до constructor
нового объекта.
Примечание: большинство классов, для которых я использую это, нельзя скопировать
class Foo
{
public:
Foo() : m_i(0) {}
Foo(int i) : m_i(i) {}
Foo(Foo&& rhs);
Foo& operator=(Foo rhs);
friend void swap(Foo& lhs, Foo& rhs);
private:
Foo(Foo& rhs) {} // uncopyable object
int m_i;
};
Foo::Foo(Foo&& rhs)
: Foo()
{
swap(*this, rhs);
}
Foo& Foo::operator=(Foo rhs)
{
swap(*this, rhs);
return *this;
}
void swap(Foo& lhs, Foo& rhs)
{
using std::swap;
swap(lhs.m_i, rhs.m_i);
}
int main()
{
Foo f(123);
f = Foo(321); // at one time both Foo(123) and Foo(321) exist in memory
}
Затем я научил, возможно, переписать operator=
сначала вручную вызвать destructor
а затем сделать swap
(в этом случае rhs
будет взят по константной ссылке). Однако этот ответ на stackOverflow заставил меня думать иначе.
Мне очень нравится operator= для сброса моих объектов, потому что код чистый и такой же, как для встроенных типов (например, int). Он также использует как код из constructor
а также destructor
, поэтому не нужно писать и поддерживать дополнительный код.
Итак, мой вопрос: есть ли способ достичь моей цели, чтобы сбросить мой объект с чистым кодом и без лишнего кода, который нужно написать, и уничтожить ли объект до создания нового?
2 ответа
По определению, если вы присваиваете новое значение старому объекту, новое значение было создано до того, как может произойти присвоение.
Ваш "старый объект" тоже не разрушен.
Так нет. Нет пути. И не должно: вы не должны переопределять "очевидное" поведение оператора присваивания.
Но здесь может помочь размещение нового, кроме тильды и экзотического синтаксиса конструкции, возможно, этот код подходит к "чистому":)
Foo old(a, b, c);
old.~Foo(); // explicit destruction
new (&old) Foo(d, e, f);
Если в конструкторе имеется код, который также должен вызываться оператором присваивания, поместите этот код в закрытую функцию-член и вызовите его как из деструктора, так и из оператора присваивания.
Ваш объект не будет разрушен (и вы не хотите, чтобы он был действительно), но он будет делать то же самое, что и деструктор.