pimpl:避免使用 pimpl 指向指针

发布于 2024-10-30 19:03:05 字数 802 浏览 5 评论 0原文

在这个问题中,我问“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心如狂蝶 2024-11-06 19:03:05

根据您的限制,有多种可能的方法。

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 用法。

缺点:

  1. 对象的类型不是shared_ptr而是shared_ptr_my_pimpl;它只是假装是一个shared_ptr
  2. 您无法获取该对象的 my_pimpl*my_pimpl&;这是一种不同的类型,但行为相同。

2. 从接口派生

创建一个接口my_pimpl_interface,其中所有相关函数均为纯虚函数。从该接口派生 my_pimplmy_pimpl::impl (您的 pimpl 实现类)。添加一个函数 make_shared_my_pimpl,它将 shared_ptr 返回到 my_pimpl::impl。您现在可以将普通对象和shared_ptr 对象引用为my_pimpl_interface&

缺点:

  1. 通过将所有函数设为虚拟,您在调用它们时会产生额外的间接性,这可能是您试图避免的。您的标准 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 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:

  1. The type of the object is not shared_ptr<x> but shared_ptr_my_pimpl; it's just pretending to be a shared_ptr.
  2. You can't get a my_pimpl* or my_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:

  1. 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.
花开半夏魅人心 2024-11-06 19:03:05

您应该为此目的使用接口,因为这样您的类的用户就可以选择是否要使用 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 or unique_ptr.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文