什么时候应该将shared_ptr作为原始指针传递?

问题描述

我正在阅读共享指针应该如何传递。 我碰到了这个link,其中指出

指南:仅使用非常量shared_ptr&参数来修改 shared_ptr。仅当您不使用const shared_ptr&作为参数时, 确定您是否要复制并共享所有权;除此以外 改用widget *(或者,如果不能为null,则使用widget&)。

关于上述声明,我有两个问题

问题1:

它说明

..否则请使用widget *(或者,如果不能为空,则使用widget&)。

这是否意味着我们有这样的东西

std::shared_ptr<foo> f = std::make_shared<foo>();

我们需要将其传递给其他方法。该方法应具有类似

的签名
void doSomething(foo* ptr); //assuming its nullable

因此要使用它

doSomething(f.get());

这是正确的吗?如果是这样,那将不危险吗?如果f的参考计数为0,那么ptr基本上是无效的?在哪种情况下,我想创建一个使用原始指针的方法?我为什么要像这样传递一个智能指针?

问题2 修改在这里是什么意思?如何修改共享指针?

仅使用非常量shared_ptr&参数来修改shared_ptr

解决方法

我将尝试问题2 :修改共享指针意味着分配一个不同的对象实例(并放弃先前拥有的指针的所有权)。

#include <memory>
#include <iostream>

int
main() {
    using intptr = std::shared_ptr<int>;
    intptr p = std::make_shared<int>(5);
    auto func = [](intptr &x) { x = std::make_shared<int>(6);};

    std::cout << *p << std::endl;
    func(p);
    std::cout << *p << std::endl;
    return 0;
}
,

所有这些都是简化代码和提高可读性的考虑,其中功能签名用作功能含义的线索。

如果函数在访问对象时要求对象的指针处于共享状态,则除非将函数用于获取所有权,否则将其作为共享指针传递是没有实际意义的。即具有签名的功能foo()

void  foo( std::shared_ptr<Object> p);  // it shares ownership

将获取对象实例的控制权,因为参数pfoo()局部变量

具有非常量引用签名的函数引起了人们对它们实际含义的怀疑:

void  foo( std::shared_ptr<Object>& p);  // new storage may be assigned

他们可以更改共享指针p所拥有的对象,也可以通过调用其reset()方法来更改- modify -指针本身。该准则建议将其用于后者,因为使用共享状态解除对指针的引用会增加成本。前一个任务可以很容易地通过原始引用来完成:

void  foo( Object& p);  // object may change but occupies same storage

如果.get()的结果可以为nullptr,则原始指针才有意义,否则受控对象最好通过引用传递。

最后,常量引用允许创建另一个共享或弱指针或更改对象,但不允许修改原始指针。此签名表明foo()可以做前者。

void  foo(const shared_ptr<Object>& p); // p cannot be changed but may be shared