TR1引入了shared_ptr,weak_ptr,scoped_ptr和unique_ptr等。
我想知道这些类型之间的各种转换/类型提升规则。
例如,当scoped_ptr被分配给shared_ptr时会发生什么?这种转换是否可行/有意义以及此类转换的用例是什么?
(具体中是否有表格?)
答案 0 :(得分:12)
首先,对您的问题进行一些更正:
scoped_ptr
是Boost的一部分,不包含在C ++ TR1或C ++ 0x中(预计在C ++ 0x unique_ptr
中可以使用{{1}传统上一直使用)。
scoped_ptr
不是C ++ TR1的一部分;它是C ++ 0x的一部分(因为它依赖于rvalue引用和移动语义,它们仅在C ++ 0x中可用)。
要回答您的问题:unique_ptr
和shared_ptr
齐头并进。 weak_ptr
所拥有的对象也可以由shared_ptr
引用。它们是互补的。
weak_ptr
拥有其管理的对象的唯一所有权;没有其他人可以拥有该对象的所有权。这与unique_ptr
的所有权语义相反:使用shared_ptr
,您拥有非共享的唯一所有权;使用unique_ptr
您拥有共享的,非唯一的所有权。
您可以从shared_ptr
构建shared_ptr
;执行此操作时,unique_ptr
将失去对象的所有权。这是有效的,因为您始终知道给定的unique_ptr
始终是对象的唯一所有者,因此它能够释放该所有权。
一旦对象归unique_ptr
所有,您就无法释放该对象的所有权,因为无法保证给定的shared_ptr
是该对象的唯一所有者。
答案 1 :(得分:3)
给定两个类A
和B
(可能是智能指针类型),有四种主要方法可以将B
类型的实例转换为类型A
:
(故意删除)。A
是B
的可访问基类对象(例如B
是从A
公开派生的),转换可以切片或者只是调整引用或指针的类型。
A
有一个可访问的构造函数,其中包含B
。
B
有一个可访问的转换运算符,生成A
。
存在一些函数需要B
并生成A
,并且您正在调用该函数。
对于智能指针,继承不用于促进转换,因为继承允许不正确的转换;因此上面的罢工。例如,如果SmartPtr<Derived>
从SmartPtr<Base>
公开继承,则可以SmartPtr<Base>& spBase = spDerived;
进行spBase = spOtherDerived
,然后例如const
,这会有相当大的问题......在适当高的抽象层次上,这与针对指针转换的auto_ptr
基本相同;请参阅常见问题解答18.17 "Why am I getting an error converting a Foo** → Foo const**?"。
因此,智能指针转换通常通过最后三个要点表示,即构造函数,转换运算符和命名转换函数。
基本上C ++ 0x中有三个智能指针,忽略了已弃用的std::unique_ptr
:
std::unique_ptr
。
std::shared_ptr
。
unique_ptr
。
auto_ptr
表达所有权转移,正如旧auto_ptr
所做的那样。但unique_ptr
不支持数组。 unique_ptr
会这样做,这会影响可能的转化。
对于单个对象,unique_ptr
通过构造函数支持相应原始指针所做的转换。它有一个带有unique_ptr
其他类型的模板化构造函数。参见例如C ++ 0x草案N3126§20.9.10.2。
但是,对于那些与原始指针一样危险的数组!因此,对于数组unique_ptr
,不提供基本/派生转换。参见例如C ++ 0x草案N3126§20.9.10.3。
由于shared_ptr
表达了所有权转移,而shared_ptr
表达了共享所有权,因此无法从unique_ptr
向shared_ptr
进行安全的常规转换。但是,另一方面,Boost auto_ptr
有一个构造函数取shared_ptr
,而C ++ 0x unique_ptr
保留了这个(也有它)并自然地添加一个构造函数{{1 }}。参见C ++ 0x draftN3126§20.9.11.2/ 1。
shared_ptr
通过构造函数和概念上实现“强制转换”的自由函数提供基本/派生转换。从本质上讲,这意味着shared_ptr
直接用于类类型对象的数组非常危险。为此,请将其包裹起来。
如上所述,从shared_ptr
转换为unique_ptr
不支持作为一般操作。因为共享所有权与所有权转移不直接兼容。但是,无视复杂性。线程安全,shared_ptr::unique
告诉您是否有单一所有者(即您的实例),然后,如果您具有如何构建初始shared_ptr
的必要知识,您可以使用自由函数get_deleter
来获取指向删除函数的指针,并执行一些低级别的恶作剧。如果你完全理解我在这里所说的话,那么很好,很好。如果没有,那么我最好不要提供更多细节,因为这是一个非常特殊的案例,它需要非常小心,而且你真的知道你在做什么。 ; - )
嗯,就是这样。我不是在讨论weak_ptr
,因为它只是shared_ptr
功能的一部分。但希望以上就是你所要求的。
答案 2 :(得分:2)
scoped_ptr
AFAIK不属于TR1(如果我错了,请纠正我)。通常boost
的{{1}}根本无法转让所有权。指定指针后,就无法释放它。scoped_ptr
只能使用unique_ptr
转让所有权,因此也不会转让所有权。std::move
无法释放所有权,因为其他指针可能与之共享。它可以转换为shared_ptr
。如果你试图从weak_ptr
转换它并且对象被释放它会抛出。weak_ptr
可以从weak_ptr
创建,转换为shared_ptr
时,如果该对象不再存在,它可能会抛出。