【问题标题】:Replacing shared_ptr elements in std::vector替换 std::vector 中的 shared_ptr 元素
【发布时间】:2016-09-21 00:02:54
【问题描述】:

我有一个 shared_ptrs 的向量,如下所示。

std::vector<std::shared_ptr<SharedThing>> things;

现在假设我将一些 shared_ptrs 推送到向量上,现在每个元素的引用计数为 1。

当我需要用新的 shared_ptr 替换其中一个元素时,我希望旧的 shared_ptr 超出范围。常规元素分配会实现这一点还是只是复制 shared_ptr 内容。例如:

things.at(0) = new_shared_ptr;

这会减少 things.at(0) 的引用计数并增加 new_shared_ptr 的计数吗?

【问题讨论】:

标签: c++ c++11 vector shared-ptr


【解决方案1】:

当我需要用新的 shared_ptr 替换其中一个元素时,我 希望旧的 shared_ptr 超出范围。将正则元素 任务实现这个?

向量中的共享指针不会超出范围,
但它将用给定的新对象替换托管对象。

调用:

things.at(0) = new_shared_ptr;

将保留计数为 1。

这是观察这种行为的一种简单方法:

#include <iostream>
#include <vector>
#include <memory>

int main(){

  //vector with a shared pointer
  std::vector<std::shared_ptr<int>> things;
  things.push_back(std::make_shared<int>(1));

  //prints 1
  std::cout << things.at(0).use_count() << '\n';

  //assign a new value
  things.at(0) = std::make_shared<int>(2);

  //still prints 1
  std::cout << things.at(0).use_count() << '\n';
}

虽然不是您的问题的一部分,但通常建议使用 make_shared 而不是 new

【讨论】:

  • 这不是“保留计数”,您正在从完全不同的对象中读取计数。 (使用计数不是shared_ptr的一部分,而是目标对象的元数据块的一部分)
【解决方案2】:

是的,基本上你是对的。
更准确地说,先前 shared_ptr at(0) 的引用计数将递减。然后为它分配一个新的 shared_ptr,它的计数可能为 1。看起来 (0) 处的引用计数是相同的,但它变了又变回来了。

你可以通过std::shared_ptr::use_cout()来验证

更多细节,我们可以调试到 STL 中,当 things.at(0) = new_shared_ptr;

include/c++/4.8.3/bits/shared_ptr_base.h:556

  __shared_count&
  operator=(const __shared_count& __r) noexcept
  {    
_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
if (__tmp != _M_pi)
  {    
    if (__tmp != 0)
      __tmp->_M_add_ref_copy();
    if (_M_pi != 0)
      _M_pi->_M_release();
    _M_pi = __tmp;
  }    
return *this;
  }    

新的 _M_add_ref_copy(),然后是前一个 _M_release(),这会将 _M_use_count 减 1。

【讨论】:

    猜你喜欢
    • 2019-10-20
    • 2018-02-02
    • 2016-02-04
    • 1970-01-01
    • 2011-12-27
    • 2018-01-11
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多