如何创建指向成员的shared_ptr?

6
我不确定我更加遭受文档错误还是头痛的折磨,所以...
我的目标是创建一个shared_ptr,它与另一个shared_ptr共享所有权,但引用对象的成员而不是整个对象。这是一个简单的示例,起点...
struct s
{
  int a, b;
};

shared_ptr<s> s1 (new s);  //  pointing to whole object

来自en.cppreference.com,shared_ptr的第8个构造函数是...

template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );

描述提到“构造一个shared_ptr与r共享所有权信息,但持有一个不相关且未受管理的指针ptr...例如在典型用例中,ptr是由r管理的对象的成员。”
那么...这个构造函数中的模板参数T是不是只是被意外地省略了呢?还是我漏了什么?实际上,Y看起来对我也是错误的,所以这个构造函数的描述是否正确?
我希望能够做的事情就像这样...
shared_ptr<int> s2 (s1, &(s1.get ()->a));

s2指向成员a(一个int),但与s1共享整个对象的所有权。

这合理吗?


也许我漏掉了什么,但是为什么你想要一个 shared_ptr 指向一个没有在堆上分配的成员变量呢?也就是说,为什么不只是使用一个原始指针来代替 s2 呢? - RC.
@RC - 确保如果原始 shared_ptr 被释放,对象本身不会被释放 - 即确保 s2 不成为悬空指针。在现实世界的例子中,s1 和 s2 的作用域不会相同。 - user180247
是的,这很正常。而且你不需要使用.get() - atzz
啊...我从未像那样使用过shared_ptr。@Steve314,根据您的评论,然后检查文档,这很有道理。不知道你可以那样做。今天学到了新东西。谢谢! - RC.
3个回答

9

T参数是shared_ptr本身的模板参数,而Y参数是该特定shared_ptr构造函数的模板参数。类似于这样:

template< class T >
class shared_ptr
{
     template< class Y >
     shared_ptr( const shared_ptr<Y>& r, T *ptr );
}

关于您发布的示例代码,我认为看起来很不错。


每个人都有自己的优势-你因为快了一点而赢得胜利。我感觉有点愚蠢 - 很明显我最近没有多做模板方面的工作。 我完全忘记了成员模板。 - user180247

4

文档是正确的。你忘记了这是类模板 shared_ptr<T> 上的构造函数的文档,即构造函数的类限定声明为:

template<typename T>
template<typename Y>
shared_ptr<T>::shared_ptr(const shared_ptr<Y>& r, T *ptr);

因此,在您的示例中,TintYs


2

T是类的模板参数,而不是构造函数的模板参数。这正好符合需求:一个成员指针必须具有成员类型并且忘记/消除(参见类型擦除)包含对象(在本例中为Y)的类型。

您发布的代码应该可以工作,您甚至可以将其简化为:

shared_ptr<int> s2 (s1, &s1->a);

由于某种原因,我从来不确定&的优先级 - 可能是因为我总是添加额外的括号而不是检查。get也是故意的,但我不确定使事情更明确的理由是否有意义。我真的应该坚持归咎于我的头痛。 - user180247

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接