我一直在努力思考 C++11 中的移动语义应该如何工作,并且在理解移动对象需要满足哪些条件时遇到了很多麻烦。在这里查看答案并不能真正解决我的问题,因为尽管移动语义的论点非常适合 pimpls,但看不到如何以合理的方式将其应用于 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
是一个合理的不变量的想法吗?