如何遍历一系列shared_ptr对象?

qua*_*ant 8 c++ reference shared-ptr c++11

这更像是一个造型而不是性能问题.我刚刚转换了(大部分)指向shared_ptr对象的指针,并且不情愿地接受weak_ptrs作为原始指针的替代品.我的问题是,迭代共享指针对象的序列(比如说一个向量)的首选方法是什么?这是我一直在做的事情:

std::vector<std::shared_ptr<A>> my_sequence;
// Do something to fill my_sequence;

for (std::shared_ptr<A> const& ptr : my_sequence)
{
  ptr->AMethod();
}
Run Code Online (Sandbox Code Playgroud)

这违背了*不要使用shared_ptr references*规则,那么什么是一个好的选择,为什么呢?

我会问的问题是; 技术是否健全,即.对于AMethod()超小,my_sequence超大,这个方法会因shared_ptr副本而开始阻碍性能吗?它可读吗?这很简单吗?

Adr*_*ian 8

不使用shared_ptr引用的原因是因为你击败了它试图保护自己的机制.即有一个潜在的悬垂指针.如果您正在迭代容器,这应该不是问题,因为对象不会意外地消失在您身上.您不应该存储以后可能使用的shared_ptr引用.

即这很糟糕:

struct Y
{
    int y;
    Y() : y(1) {}
};

struct X
{
     shared_ptr<Y>& ref_shared_ptr_y;
     X(shared_ptr<Y>& y) : ref_shared_ptr_y(y) {}
};

void main()
{
    shared_ptr<Y> shared_ptr_y(new Y());
    X x(shared_ptr_y);
    y.reset();
    x.ref_shared_ptr_y->y;  // UB since x.ref_shared_ptr_y was deleted
}
Run Code Online (Sandbox Code Playgroud)

shared_ptr只有在您确实需要在2个或更多位置之间共享对象所有权时才应使用.否则会导致不必要的开销,并表明您并未真正考虑过所有者关系.如果您的所有权仅限于一个地点,请使用unique_ptr.

  • 这通常扩展到原始指针和引用与`shared_pointer`.如果没有所有权问题,`shared_pointer`是错误的工具.(上帝禁止你将两个`shared_pointers`独立地链接到同一个对象.) (4认同)

Pot*_*ter 7

首先,免责声明:

shared_ptr不是灵丹妙药.在实际共享所有权时应该使用它.非共享所有权unique_ptr由(原始)引用表示,非所有权由(原始)引用表示.weak_ptr是一个shared_ptr必须观察但不归属的......但是对于一般的过时指针来说,这不是一个好的防守练习.违约shared_ptr直接达到最低标准; 这是糟糕的编程习惯.


这里的选择之间shared_ptr< T >,shared_ptr< T const >,shared_ptr< T > const &,和T const &T &.让我们假设你没有改变任何东西,但序列可以改变它的对象,所以const是可取的.这缩小它shared_ptr< T const >,shared_ptr< T > const &T const &.

让我们重新提出这个问题,

shared_ptr< T > const &永远正确的选择?

从这个角度来看,评估替代方案.

  • shared_ptr< T const > (按值传递共享指针)

    • +:直接的价值语义; 可以通过shared_ptr< T >
    • +:可以复制或moved扩展所有权池
    • +:将const正确性传播给被调用函数
    • +:对象的访问速度很快:包含直接指针参数
    • - :传递很昂贵:复制两个机器字和原子触摸一个引用计数
    • - :被调用函数关注所有权语义
  • shared_ptr< T > const & (通过引用传递共享指针)

    • +:传递与直接对象引用一样便宜
    • +:可以复制以扩展所有权池
    • - :失去const对被调用函数的正确性

      • 如果您尝试shared_ptr< T const > const &改为,则会传递临时副本,最终会遇到此替代方案和按值传递的缺点.
    • - :对象的访问通过额外的间接

    • - :被调用函数关注所有权语义
  • T const & (直接参考)

    • +:保持const正确性
    • +:调用者不关心所有权语义
    • +:快速通过,只需一个机器字
    • +:访问函数的快速,直接指针参数(如果是这样)
    • - :不能授予所有权

权衡它,如果没有扩展所有权(例如通过返回保留参数的对象),你真的应该传递一个简单的引用.在这种情况下,函数应该很少关心它的参数是如何拥有的.需要以shared_ptr最糟糕的方式违反关注点.您不能拥有本地对象或成员子对象,仍然可以使用该功能.最糟糕的是,一切都变得更加复杂.

如果所有权可能扩展到其他人,这将是shared_ptr首先使用的理由,那么您应该始终按shared_ptr< [const] T >值传递.是的,它确实复制了shared_ptr随叫随到.但复制a的昂贵部分shared_ptr是更新引用计数,而不是推送堆栈上的指针.如果您要授予所有权,则无论如何都要更新引用计数.获取传递的值,move不会触及引用计数.完成后,你没有任何优势和许多缺点,以便通过引用传递.