scoped_ptr 非常适合这个目的。但是必须了解它的语义。您可以使用两个主要属性对智能指针进行分组:
- 可复制:可以复制智能指针:副本和原始共享所有权。
- 可移动:可以移动智能指针:移动结果将拥有所有权,原来的将不再拥有。
这是相当常见的术语。对于智能指针,有一个特定的术语可以更好地标记这些属性:
- 所有权转移:智能指针是可移动的
- 所有权份额:智能指针是可复制的。如果智能指针已经是可复制的,则很容易支持所有权转移语义:那只是一个原子复制和重置原始操作,将其限制为某些类型的智能指针(例如,仅临时智能指针)。
(C)opyable
让我们使用, 和(M)ovable
,对可用的智能指针进行分组(N)either
:
boost::scoped_ptr
: N
std::auto_ptr
: 米
boost::shared_ptr
: C
auto_ptr
有一个大问题,它使用复制构造函数来实现 Movable 的概念。这是因为当 auto_ptr 被 C++ 接受时,与新的 C++ 标准相反,还没有一种方法可以使用移动构造函数本地支持移动语义。也就是说,您可以使用 auto_ptr 执行以下操作,并且它可以工作:
auto_ptr<int> a(new int), b;
// oops, after this, a is reset. But a copy was desired!
// it does the copy&reset-of-original, but it's not restricted to only temporary
// auto_ptrs (so, not to ones that are returned from functions, for example).
b = a;
无论如何,正如我们所看到的,在您的情况下,您将无法将所有权转移给另一个对象:您的对象实际上是不可复制的。在下一个 C++ 标准中,如果您使用 scoped_ptr,它将是不可移动的。
要使用 scoped_ptr 实现您的类,请注意您是否满足以下两点之一:
- 在类的 .cpp 文件中写一个析构函数(即使它是空的),或者
- 制作
Owned
一个完全定义的类。
否则,当你创建一个 Example 的对象时,编译器会为你隐式定义一个析构函数,它会调用 scoped_ptr 的析构函数:
~Example() { ptr.~scoped_ptr<Owned>(); }
然后,如果您没有完成上述两点中的任何一项,这将使 scoped_ptr callboost::checked_delete
抱怨不完整。Owned
如果您在 .cpp 文件中定义了自己的 dtor,则对 scoped_ptr 的析构函数的隐式调用将从 .cpp 文件中进行,您可以在其中放置Owned
类的定义。
您对 auto_ptr 有同样的问题,但还有一个问题:为 auto_ptr 提供不完整的类型目前是未定义的行为(可能会在下一个 C++ 版本中修复)。因此,当您使用 auto_ptr 时,您必须在头文件中使 Owned 成为一个完整的类型。
shared_ptr 没有这个问题,因为它使用了一个多态删除器,它间接调用了删除。所以deleting函数不是在析构函数被实例化的时候被实例化,而是在shared_ptr的构造函数中创建deleter的时候。