从函数返回shared_ptr的解除引用值

时间:2017-02-01 15:31:28

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

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

shared_ptr

首先会发生什么?通过导致内存故障复制/ NRVO /移动或破坏{{1}}?如果不安全,我的替代方案是什么?

3 个答案:

答案 0 :(得分:8)

发生这种情况:

  • 制作指向对象的临时副本。这是函数的返回值。该副本不能被删除。
  • 该函数的局部变量(包括共享指针)将被销毁。
  • 当共享指针被销毁时,refcount将递减。如果在函数中没有创建共享指针的副本,则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可以应用于此,如果未应用,则返回值由移动构建。

答案 1 :(得分:4)

  

通过导致内存故障来复制/ NRVO /移动或破坏shared_ptr?

好吧,让我们考虑一下。考虑这个功能:

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

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

  1. x被复制到返回值中,然后x被销毁。
  2. x被销毁,然后x被复制到返回值中。
  3. (2)的含义是这样的代码将是未定义的行为,这使得几乎不可能编写函数 - 因为你不能返回任何局部变量。因此,从语言理智设计的角度来看,最好是(1)。

    显式规则在[stmt.return]:

      

    调用结果的复制初始化在由return语句的操作数建立的完整表达式结尾处的临时销毁之前排序,而后者依次是之前排序   包含return语句的块的局部变量(6.6)的破坏。

答案 2 :(得分:2)

您的shared_ptr没有做任何事情,您没有返回它,您正在返回其内容,即unordered_set本身。 您应该更改函数以返回shared_ptr并按值返回。

你可能应该使用std :: not boost(除非这是一个旧的编译器)。