pimpl:使用pimpl避免指针指针 [英] pimpl: Avoiding pointer to pointer with pimpl
问题描述
在此问题中,我问了pimpl:shared_ptr或unique_ptr我已经确信pimpl成语的正确使用是使用 unique_ptr
,而不是 shared_ptr
。它应该对用户起作用,就像根本没有指针一样,但是很清楚, shared_ptr
在复制时引入了别名,这肯定像一个指针。
shared_ptr
到我的pimpl对象(假设他们想要实际上想要多个别名) 。例如: 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)指向这里指针的指针。
x.f(); //(3)
p-> f(); //(4)
但是无论如何摆脱指针的指针,隐藏pimpl。
任何想法如何实现这一点(我很乐意改变行(2),显然 my_pimpl
,但要让行(3)和(4)保持不变。)
可能的方法取决于你的约束。
1。创建您自己的shared_my_pimpl类
创建一个类 shared_my_pimpl
,其接口与 my_pimpl
,但是在内部使用shared_ptr而不是 unique_ptr
。现在创建一个 shared_ptr_my_pimpl
,其中包含 shared_my_pimpl
,并且具有 operator-> code>,它返回一个指向
成员访问的符号。您可以添加一个函数 shared_my_pimpl
的指针,所以你得到 - >
code>。 make_shared_ptr_my_pimpl
,使其看起来更像 shared_ptr
的用法。
缺点:
- 对象的类型不是
shared_ptr< x>
但shared_ptr_my_pimpl
;它只是假装是一个shared_ptr
。 - 你不能得到
my_pimpl *
或my_pimpl&
它是一种不同的类型,只是表现相同。
2。从接口派生
使用所有相关函数pure virtual创建一个接口 my_pimpl_interface
。从此接口派生 my_pimpl
和 my_pimpl :: impl
(您的pimpl实现类)。添加一个函数 make_shared_my_pimpl
,它返回 shared_ptr< my_pimpl_interface>
到 my_pimpl :: impl
。现在可以引用plain对象和shared_ptr对象作为 my_pimpl_interface&
。
缺点:
- 通过使所有函数虚函数,您在调用它们时会产生额外的间接,这可能是您想要避免的。您的标准
my_pimpl
对象也会支付此开销。
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).
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 as my_pimpl
but internally uses a shared_ptr instead of a unique_ptr
. Now create a class shared_ptr_my_pimpl
which holds a shared_my_pimpl
and has an operator->
which returns a pointer to the shared_my_pimpl
, so that you get ->
notation instead of .
notation for member access. You can add a function make_shared_ptr_my_pimpl
to make it look more like shared_ptr
usage.
Disadvantages:
- The type of the object is not
shared_ptr<x>
butshared_ptr_my_pimpl
; it's just pretending to be ashared_ptr
. - You can't get a
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 both my_pimpl
and my_pimpl::impl
(your pimpl implementation class) from this interface. Add a function make_shared_my_pimpl
which returns a shared_ptr<my_pimpl_interface>
to a my_pimpl::impl
. You can now refer to both the plain object and the shared_ptr object as my_pimpl_interface&
.
Disadvantages:
- By making all functions virtual you incur an extra indirection in calling them, which may have been what you were trying to avoid. Your standard
my_pimpl
object will also pay this overhead.
这篇关于pimpl:使用pimpl避免指针指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!