12

TR1 引入了 shared_ptr、weak_ptr、scoped_ptr 和 unique_ptr 等。

我想知道这些类型之间的各种转换/类型提升规则。

例如,将 scoped_ptr 分配给 shared_ptr 时会发生什么?这种转换是否可能/有意义?这种转换有哪些用例?

(规范中有表格吗?)

4

3 回答 3

13

首先,对您的问题进行一些更正:

  • scoped_ptr是 Boost 的一部分,不包含在 C++ TR1 或 C++0x 中(预计在 C++0xunique_ptr中可以在scoped_ptr传统上使用的地方使用)。

  • unique_ptr不是 C++ TR1 的一部分;它是 C++0x 的一部分(因为它依赖于右值引用和移动语义,这些仅在 C++0x 中可用)。

回答你的问题: 携手并进shared_ptrweak_ptra 拥有的对象shared_ptr也可以被 a 引用weak_ptr。它们是互补的。

Aunique_ptr对其管理的对象拥有唯一所有权;没有其他人可以拥有该对象的所有权。这与 的所有权语义相反shared_ptr:使用 a unique_ptr,您拥有非共享的唯一所有权;与shared_ptr您共享的非唯一所有权。

您可以shared_ptr从 a 构造 a unique_ptr; 当你这样做时,unique_ptr失去对象的所有权。这是有效的,因为您始终知道给定unique_ptr对象始终是对象的唯一所有者,因此它能够释放该所有权。

一旦对象由 a 拥有shared_ptr,您就不能释放该对象的所有权,因为不能保证给定shared_ptr的是该对象的唯一所有者。

于 2010-11-21T08:52:05.397 回答
3

给定两个类Aand B(可能是智能指针类型),有四种主要方法可以将 type 的实例转换B为 type A

  • A是一个可访问的基类对象B(例如B从 公开派生A),并且转换可以切片或简单地调整引用或指针的类型。(故意划线)。

  • A有一个可访问的构造函数,采用B.

  • B有一个可访问的转换运算符产生一个A.

  • 存在一些接受 aB并产生 a 的函数A,而您正在调用该函数。

对于智能指针,继承不用于促进转换,因为继承允许不正确的转换;因此在上面删除。例如,如果SmartPtr<Derived>从 公开继承SmartPtr<Base>,则可以执行SmartPtr<Base>& spBase = spDerived;,然后例如spBase = spOtherDerived,这将是相当有问题的……在适当的高级抽象上,这与指针转换的问题基本相同const;请参阅 FAQ 项目18.17 “为什么我在转换 Foo** → Foo const** 时出现错误?” .

因此,智能指针转换通常通过最后三个要点表示,即构造函数、转换运算符和命名转换函数。

本质上,C++0x 中有三个智能指针,忽略 deprecated auto_ptr

  • std::unique_ptr对于单个对象。

  • std::unique_ptr对于数组。

  • std::shared_ptr对于单个对象。

unique_ptr表示所有权转让,就像旧的auto_ptr一样。但auto_ptr不支持数组。unique_ptr确实如此,这会影响可能的转换。

对于单个对象,unique_ptr支持对应的原始指针通过构造函数进行的转换。它有一个unique_ptr采用其他类型的模板化构造函数。参见例如 C++0x 草案 N3126 §20.9.10.2。

但是,对于与原始指针一样危险的数组!因此对于数组unique_ptr提供基本/派生转换。参见例如 C++0x 草案 N3126 §20.9.10.3。

由于在表示共享所有权unique_ptr的同时表示所有权转移,因此无法从到进行安全的一般转换。但是,另外一种方式,Boost有一个构造函数 take ,而 C++0x保留了 this (也有它),自然而然地添加了一个构造函数taking 。参见 C++0x 草案 N3126 §20.9.11.2/1。shared_ptrshared_ptrunique_ptrshared_ptrauto_ptrshared_ptrunique_ptr

shared_ptr通过构造函数和概念上实现“强制转换”的自由函数提供基本/派生转换。从本质上讲,这意味着shared_ptr直接用于类类型对象的数组是非常危险的。为了那个用途,把它包起来。

如前所述,不支持将 from 转换shared_ptr为一般操作。unique_ptr因为共享所有权与所有权转移不直接兼容。但是,忽略并发症。线程安全,shared_ptr::unique告诉您是否有一个所有者(即您的实例),然后,如果您对如何shared_ptr构造初始值有必要的了解,则可以使用 free 函数get_deleter获取指向删除器函数的指针,然后执行一些低级的恶作剧。如果你完全理解我在这里所说的,那么很好,很好。如果没有,那么我最好不要提供更多细节,因为这是一个非常非常特殊的情况,需要非常小心,并且您真的知道自己在做什么™。;-)

嗯,就是这样。我不是在讨论weak_ptr,因为它只是shared_ptr功能的一部分。但希望以上是您要问的。

于 2010-11-21T09:45:28.400 回答
2
  1. scoped_ptrAFAIK 不是 TR1 的一部分(如果我错了,请纠正我)。通常根本无法转让所有权boostscoped_ptr一旦你给它分配了指针,你就不能释放它。
  2. unique_ptr只能使用转让所有权std::move,因此它也不会转让所有权。
  3. shared_ptr无法释放所有权,因为其他指针可能与之共享。它可以转换为weak_ptr. 如果您尝试转换它weak_ptr并且对象被释放,它会抛出。
  4. weak_ptr可以从 中创建,如果对象不再存在,则shared_ptr转换为它可能会抛出。shared_ptr
于 2010-11-21T08:55:40.383 回答