【发布时间】:2016-01-27 10:30:53
【问题描述】:
我正在使用一个库,其中包含许多使用 PIMPL 习语构建的类。在我看来,我发现不好的是这些类是使用std::shared_ptr 实现的。这意味着对象实际上是“隐式共享的”。我的问题是:这是实现 PIMPL 的正确方法吗?或者 PIMPL 和“隐式共享”是两个不同的习语,因此默认情况下不应混用?处理复制语义的正确方法是什么?
【问题讨论】:
标签: c++ deep-copy pimpl-idiom
我正在使用一个库,其中包含许多使用 PIMPL 习语构建的类。在我看来,我发现不好的是这些类是使用std::shared_ptr 实现的。这意味着对象实际上是“隐式共享的”。我的问题是:这是实现 PIMPL 的正确方法吗?或者 PIMPL 和“隐式共享”是两个不同的习语,因此默认情况下不应混用?处理复制语义的正确方法是什么?
【问题讨论】:
标签: c++ deep-copy pimpl-idiom
IMO,实现 pimpl 的正确方法是使用std::unique_ptr。
它更高效,并且 pimpl 对象应该由可见类唯一拥有,而不是共享(并且您不必为复制语义而烦恼)。
PIMPL 和“隐式共享”确实是两个不同的习语。
如果您仍然必须为 pimpl 使用 std::shared_ptr,那么您将必须显式定义复制分配操作(因为编译器将无法生成正确的操作)。
【讨论】:
正如 coincoin 所说,使用 unique_ptr 而不是 shared_ptr。如果你想让你的类可复制,你总是可以在可见类的复制构造函数中调用 pimpl 对象的复制构造函数。
class A {
class impl;
std::unique_ptr<impl> pimpl;
public:
A(int x);
A(A const& old);
...
};
实施:
class A::impl {
int x;
public:
impl(int x)
: x(x) {}
impl(impl const& old)
: x(old.x) {}
};
A::A(int x)
: pimpl(std::make_unique<impl>(x)) {}
A::A(A const& old)
: pimpl(std::make_unique<impl>(*old.pimpl)) {}
【讨论】: