Что представляет собой допустимое состояние для «перемещенного объекта» в C ++ 11?
Я пытался обдумать, как семантика перемещения в C ++ 11 должна работать, и у меня возникли большие проблемы с пониманием того, каким условиям должен удовлетворять перемещенный объект. Глядя наответ здесь действительно не решает мой вопрос, потому что не может понять, как применить его к объектам pimpl разумным способом, несмотря на аргументы, которыесемантика перемещения идеально подходит для прыщей.
Самая простая иллюстрация моей проблемы включает в себя идиому pimpl, например:
class Foo {
std::unique_ptr<FooImpl> impl_;
public:
// Inlining FooImpl's constructors for brevity's sake; otherwise it
// defeats the point.
Foo() : impl_(new FooImpl()) {}
Foo(const Foo & rhs) : impl_(new FooImpl(*rhs.impl_)) {}
Foo(Foo && rhs) : impl_(std::move(rhs.impl_)) {}
Foo & operator=(Foo rhs)
{
std::swap(impl_, rhs.impl_);
return *this;
}
void do_stuff ()
{
impl_->do_stuff;
}
};
Теперь, что я могу сделать, когда я перешел изFoo
? Я могу безопасно уничтожить удаленный объект и назначить его, оба из которых абсолютно необходимы. Однако, если я попытаюсьdo_stuff
со мнойFoo
взорвется. Прежде чем я добавил семантику перемещения для моего определенияFoo
каждыйFoo
удовлетворил инвариант, что он могdo_stuff
и это уже не так. Похоже, что не существует большого количества хороших альтернатив, поскольку (например)Foo
будет включать в себя новое динамическое распределение, которое частично отвергает цель семантики перемещения. Я мог бы проверить,impl_
вdo_stuff
и инициализировать его по умолчаниюFooImpl
если это так, но это добавляет (обычно ложную) проверку, и если у меня есть много методов, это будет означать, что нужно помнить, чтобы выполнить проверку в каждом из них.
Должен ли я просто отказаться от идеи, что возможностьdo_stuff
является разумным инвариантом?