boost::shared_ptr
有一个不寻常的构造函数
template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p);
我对这对什么有用感到有些疑惑。基本上它与r
共享所有权,但.get()
将返回p
。 不 r.get()
!
这意味着您可以执行以下操作:
int main() {
boost::shared_ptr<int> x(new int);
boost::shared_ptr<int> y(x, new int);
std::cout << x.get() << std::endl;
std::cout << y.get() << std::endl;
std::cout << x.use_count() << std::endl;
std::cout << y.use_count() << std::endl;
}
你会得到这个:
0x8c66008
0x8c66030
2
2
请注意,指针是分开的,但它们都声称use_count
为2(因为它们共享同一对象的所有权)。
因此,int
拥有的x
只要x
或 y
存在就会存在。如果我理解文档是正确的,那么第二个int
永远不会被破坏。我通过以下测试程序证实了这一点:
struct T {
T() { std::cout << "T()" << std::endl; }
~T() { std::cout << "~T()" << std::endl; }
};
int main() {
boost::shared_ptr<T> x(new T);
boost::shared_ptr<T> y(x, new T);
std::cout << x.get() << std::endl;
std::cout << y.get() << std::endl;
std::cout << x.use_count() << std::endl;
std::cout << y.use_count() << std::endl;
}
此输出(如预期):
T()
T()
0x96c2008
0x96c2030
2
2
~T()
所以...这个不同的构造分享一个指针的所有权有什么用处,但行为就像另一个指针(它不拥有)在使用时。
答案 0 :(得分:29)
当您想要共享一个类成员并且该类的实例已经是shared_ptr时,它非常有用,如下所示:
struct A
{
int *B; // managed inside A
};
shared_ptr<A> a( new A );
shared_ptr<int> b( a, a->B );
他们分享使用次数和东西。它是内存使用的优化。
答案 1 :(得分:8)
要扩展leiz's和piotr's个答案,shared_ptr<>
'别名'的说明来自WG21论文,"Improving shared_ptr
for C++0x, Revision 2":
<强> III。别名支持
高级用户经常需要 能够创建
shared_ptr
与之共享所有权的实例p
另一个(主)shared_ptr
q
但是 指向不是基础的对象*q
。*p
可能是会员或 例如,*q
的元素。这个 部分提出了额外的 可用于此的构造函数 目的这有趣的副作用 表达能力的提高就是这样 现在
*_pointer_cast
函数可以 用户代码实现。该 提出了make_shared
工厂功能 稍后在本文档中也可以 仅使用公众实施 通过shared_ptr
的界面 别名构造函数。<强>影响:强>
此功能扩展了界面 向后兼容的
shared_ptr
增加其表现力的方式 力量,因此是强烈的 建议添加到C ++ 0x 标准。它没有引入任何来源和 二进制兼容性问题。提议的文字:
添加到
shared_ptr
[util.smartptr.shared]以下内容 构造:template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );
将以下内容添加到 [util.smartptr.shared.const]:
template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );
效果:构建一个
shared_ptr
实例,用{/ 1>}存储p
和共享所有权。后置条件:
r
。抛出:没有。
[注意:为了避免悬空指针的可能性,用户 这个构造函数必须确保
get() == p && use_count() == r.use_count()
至少保持有效 直到p
的所有权组被销毁。 - 结束说明。][注意:此构造函数允许创建空
r
具有非NULL存储指针的实例。 - 结束说明。]
答案 2 :(得分:4)
您也可以使用它来保持动态转换指针,即:
class A {};
class B: public A {};
shared_ptr<A> a(new B);
shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));
答案 3 :(得分:2)
您可能有指向某个驱动程序或较低级别api的数据结构的指针,该数据结构可能通过其较低级别的api或其他方式分配其他数据。在这种情况下,增加use_count可能会很有趣,但如果第一个指针拥有其他数据指针则返回附加数据。
答案 4 :(得分:0)
对于“shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));
”
我认为这不是使用智能指针的推荐方法。
执行此类型转换的推荐方法应该是:
shared_ptr<B> b(a);
因为在Boost文档中提到了:
shared_ptr<T>
可以隐式 每当T *转换为shared_ptr<U>
可以隐式转换为U *。在 特别是,shared_ptr<T>
是 隐式可转换为shared_ptr<T> const
, 至shared_ptr<U>
,其中U是 T的可访问基地,以及shared_ptr<void>
。
除此之外,我们还有 dynamic_pointer_cast 它可以直接在Smart Pointer对象上进行转换,这两种方法都比手动转换原始指针方式更安全。
答案 5 :(得分:0)
我在我的小库中使用了shared_ptr的别名构造函数:
http://code.google.com/p/infectorpp/(只是我简单的IoC容器)
关键是因为我需要从多态类(不知道类型)返回已知类型的shared_ptr。我无法将shared_ptr隐式转换为我需要的类型。
在文件“InfectorHelpers.hpp”(第72-99行)中,您可以看到对IAnyShared类型的操作。
别名构造函数创建的shared_ptr不会删除它们实际指向的指针,但是它们仍会将引用计数器增加到原始对象,这可能非常有用。
基本上,您可以使用别名构造函数创建指向任何内容的指针,并将其威胁为参考计数器。
//my class
std::shared_ptr<T> ist;
int a; //dummy variable. I need its adress
virtual std::shared_ptr<int> getReferenceCounter(){
return std::shared_ptr<int>(ist,&a); //not intended for dereferencing
}
virtual void* getPtr(); //return raw pointer to T
现在我们有“引用计数器”和指向T的istance的指针,足够的数据用于创建具有别名构造函数的东西
std::shared_ptr<T> aPtr( any->getReferenceCounter(), //share same ref counter
static_cast<T*>(any->getPtr()) ); //potentially unsafe cast!
我并没有假装为别名构造函数发明了这种用法,但我从未见过其他人这样做过。如果你猜测那些脏代码是否有效,答案是肯定的。