Return 来自函数的取消引用值 shared_ptr

Return a dereferenced value of shared_ptr from a function

这里是一个菜鸟问题。以下代码安全吗?

boost::unordered_set<std::string> func()
{
      boost::shared_ptr<boost::unordered_set<std::string>> list =
              boost::make_shared<boost::unordered_set<std::string>>();

      /* Code to populate the shared_ptr to unordered_set goes here and I do
         populate my set. */

      return *list;
}

首先会发生什么? Copying/NRVO/moving 或破坏 shared_ptr 导致内存故障?如果不安全,我有什么选择?

您的 shared_ptr 没有做任何事情,您没有 returning 它,您正在 returning 它的内容,即 unordered_set 本身。 您应该将您的函数更改为 return shared_ptr 和 return 它的值。

您可能应该使用 std:: 而不是 boost(除非这是一个旧编译器)。

Copying/NRVO/moving or destruction of shared_ptr there by causing memory fault?

好吧,让我们考虑一下。考虑这个函数:

X foo() {
    X x;
    return x;
}

这里有两个潜在的顺序,让我们忘记复制省略。

  1. x被复制到return值,然后x被销毁。
  2. x被销毁,然后x被复制到return值。

(2) 的含义是这样的代码将是未定义的行为,这使得编写函数几乎不可能 - 因为您不能 return 任何局部变量。所以从语言完整性设计的角度来看,最好是 (1).


明确的规则在[stmt.return]:

The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables (6.6) of the block enclosing the return statement.

发生这种情况:

  • 制作了指向对象的临时副本。这是函数的 return 值。复制不能省略
  • 函数的局部变量,包括共享指针被销毁。
  • 当共享指针被销毁时,引用计数递减。如果在函数内没有创建共享指针的副本,refocount 将达到 0,指向的对象将被销毁。

这是安全的,但是使用动态分配和共享指针似乎毫无意义并且如果集合很大,复制的低效率可能会影响性能。


由于您没有证明需要使用指针,我建议使用更简单的替代方法:

boost::unordered_set<std::string> list;

/* Code to populate the unordered_set goes here and I do
     populate my set. */

return list;

NRVO 可以应用于此,如果未应用,则 return 值由移动构建。