如何将shared_ptr作为参数传递给可变对象?

Ste*_*314 7 c++ boost smart-pointers c++11

我想通过智能指针引用将对象传递给函数.该函数可能会更改引用对象的值,但可能不会更改引用本身.有两种明显的方法可以解决这个问题.

第一种通过值传递shared_ptr的方法 - 它引用,因此本身不需要通过引用传递.这个问题的明显问题是复制引用,这表明一些引用计数开销.

void foo (shared_ptr<bar> p)
Run Code Online (Sandbox Code Playgroud)

第二种方法是通过const引用传递shared_ptr - 避免复制shared_ptr实例,而是暗示对引用对象的访问需要两层解除引用而不是一层.

void foo (const shared_ptr<bar> &p)
Run Code Online (Sandbox Code Playgroud)

在实践中,这些理论上的开销通常是微不足道的,无关紧要的.这告诉我,我不应该为每个案例选择一种方法,而应该遵循一些标准惯例.这导致了这个问题......

我通常应该选择哪种方法的标准惯例?如果是这样,这是传统的选择吗?

编辑 - 可能值得一提 - 考虑const-by-const-reference案例的一个原因是因为有一个预先存在的约定,大多数类/结构实例是由const-reference而不是value传递的,并且shared_ptr是一个类.当然它不是重量级的(复制成本很小),因此旧约定背后的原因可能不适用.

Xeo*_*Xeo 13

始终shared_ptr按值传递.如果你传递了一个引用,你可能会遇到这样一个问题:调用该对象的一个​​函数shared_ptr可能只是重置它,现在你有一个悬空指针.如果按值传递,则确保对象在当前函数调用后仍然存在.

请看这里了解更多信息.


例:

#include <memory>
#include <iostream>

std::shared_ptr<int> ptr(new int(42));

void foo(){
  ptr.reset();
}

void bar(std::shared_ptr<int> const& p){
  foo();
  std::cout << *p;
}

int main(){
  bar(ptr);
}
Run Code Online (Sandbox Code Playgroud)

这应该用一点盐.它可以用来证明const-reference不应该传递任何类型 - 例如http://ideone.com/1IYyC,Benjamin Lindley在评论中指出.

然而,在实践中偶然会出现这种问题的更复杂的变化.例如,这就是为什么我们被警告为什么迭代器(以及const-reference返回值)被改变引用容器的方法无效.这些规则很容易遵循,但偶尔会有更多间接和意外的例子让人感到意外.

在这种情况下,最好在不需要时避免额外的引用层.

  • @Xeo - 同意,但这是一个标准的const-by-const-reference问题,通常不会让任何人担心.如果多线程是一个问题,这是您遇到的最少问题.如果保存该引用的副本,假设这意味着复制shared_ptr实例,则应该没问题.否则,问题不会出现 - 函数外部的任何内容都不会在您使用它时更改引用,因为函数外部的任何内容都不会执行,直到函数退出并且参数无论如何都会死亡. (2认同)