pimpl:避免使用 pimpl 指向指针
在这个问题中,我问“pimpl:shared_ptr或unique_ptr”我一直在确信 pimpl 习惯用法的正确用法是使用 unique_ptr
,而不是 shared_ptr
。它应该对用户来说就像根本没有指针一样,而很明显,shared_ptr 在复制时引入了别名,这绝对像指针一样。
因此,假设用户想要为我的 pimpl 对象创建一个 shared_ptr
(假设他们实际上想要多个别名)。例如:
shared_ptr<my_pimpl> p(new my_pimpl());
这将导致 shared_ptr
指向 unique_ptr
指向我的实现。
如果我能够实现如下所示的效果,那就太好了:
my_pimpl x; // (1)
shared_ptr<my_pimpl> p(new my_pimpl()); // (2) Pointer to pointer here.
x.f(); // (3)
p->f(); // (4)
但以某种方式摆脱指向指针的指针,同时仍然保持 pimpl 的实现隐藏。
任何想法如何实现这一点(我很高兴更改第 (2) 行,显然是 my_pimpl
,但希望第 (3) 行和第 (4) 行保持不变)。
In this question I asked "pimpl: shared_ptr or unique_ptr" I've been convinced that the proper usage of the pimpl idiom is to use a unique_ptr
, not a shared_ptr
. It should act to the user as if there is no pointer at all, whereas quite clearly the shared_ptr
introduces aliasing upon copying, which definitely acts like a pointer.
So, lets say a user wants to create a shared_ptr
to my pimpl object (say if they want actually want multiple aliases to it). For example:
shared_ptr<my_pimpl> p(new my_pimpl());
That would result in a shared_ptr
pointing to a unique_ptr
pointing to my implementation.
It would be nice if I could achieve something like the following:
my_pimpl x; // (1)
shared_ptr<my_pimpl> p(new my_pimpl()); // (2) Pointer to pointer here.
x.f(); // (3)
p->f(); // (4)
but with somehow getting rid of the pointer to pointer, whilst still maintaining the implementation hiding of pimpl.
Any ideas how to achieve this (I'm happy to change the line (2) and obviously my_pimpl
, but want lines (3) and (4) to stay the same).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据您的限制,有多种可能的方法。
1. 创建您自己的shared_my_pimpl 类
创建一个类
shared_my_pimpl
,它与my_pimpl
具有相同的接口,但内部使用shared_ptr 而不是unique_ptr
。现在创建一个类shared_ptr_my_pimpl
,它保存一个shared_my_pimpl
并有一个operator->
返回指向shared_my_pimpl
的指针>,以便您获得成员访问的->
表示法而不是.
表示法。您可以添加一个函数make_shared_ptr_my_pimpl
使其看起来更像shared_ptr
用法。缺点:
shared_ptr
而是shared_ptr_my_pimpl
;它只是假装是一个shared_ptr
。my_pimpl*
或my_pimpl&
;这是一种不同的类型,但行为相同。2. 从接口派生
创建一个接口
my_pimpl_interface
,其中所有相关函数均为纯虚函数。从该接口派生my_pimpl
和my_pimpl::impl
(您的 pimpl 实现类)。添加一个函数make_shared_my_pimpl
,它将shared_ptr
返回到my_pimpl::impl
。您现在可以将普通对象和shared_ptr 对象引用为my_pimpl_interface&
。缺点:
my_pimpl
对象也将支付此开销。There are a number of possible approaches depending on your constraints.
1. Create your own shared_my_pimpl class
Create a class
shared_my_pimpl
which has the same interface asmy_pimpl
but internally uses a shared_ptr instead of aunique_ptr
. Now create a classshared_ptr_my_pimpl
which holds ashared_my_pimpl
and has anoperator->
which returns a pointer to theshared_my_pimpl
, so that you get->
notation instead of.
notation for member access. You can add a functionmake_shared_ptr_my_pimpl
to make it look more likeshared_ptr
usage.Disadvantages:
shared_ptr<x>
butshared_ptr_my_pimpl
; it's just pretending to be ashared_ptr
.my_pimpl*
ormy_pimpl&
to the object; it's a different type which just behaves the same.2. Derive from an interface
Create an interface
my_pimpl_interface
with all relevant functions pure virtual. Derive bothmy_pimpl
andmy_pimpl::impl
(your pimpl implementation class) from this interface. Add a functionmake_shared_my_pimpl
which returns ashared_ptr<my_pimpl_interface>
to amy_pimpl::impl
. You can now refer to both the plain object and the shared_ptr object asmy_pimpl_interface&
.Disadvantages:
my_pimpl
object will also pay this overhead.您应该为此目的使用接口,因为这样您的类的用户就可以选择是否要使用
shared_ptr
还是unique_ptr
。You should use an interface for this purpose, because then the user of your class can choose whether they want to use
shared_ptr
orunique_ptr
.