当一个函数接受一个shared_ptr(来自boost或c++ 11 STL)时,你是否传递它:
foo(const shared_ptr<T>& p) 或通过值:void foo(shared_ptr<T> p) ?
我更喜欢第一种方法,因为我怀疑它会更快。但这真的值得吗,还有其他问题吗?
你能否给出你选择的原因,或者如果是这样,为什么你认为这无关紧要。
当一个函数接受一个shared_ptr(来自boost或c++ 11 STL)时,你是否传递它:
foo(const shared_ptr<T>& p) 或通过值:void foo(shared_ptr<T> p) ?
我更喜欢第一种方法,因为我怀疑它会更快。但这真的值得吗,还有其他问题吗?
你能否给出你选择的原因,或者如果是这样,为什么你认为这无关紧要。
当前回答
我运行下面的代码,一次用foo通过const&获取shared_ptr,另一次用foo通过value获取shared_ptr。
void foo(const std::shared_ptr<int>& p)
{
static int x = 0;
*p = ++x;
}
int main()
{
auto p = std::make_shared<int>();
auto start = clock();
for (int i = 0; i < 10000000; ++i)
{
foo(p);
}
std::cout << "Took " << clock() - start << " ms" << std::endl;
}
使用VS2015, x86发布版本,在我的英特尔酷睿2四(2.4GHz)处理器上
const shared_ptr& - 10ms
shared_ptr - 281ms
按值复制的版本慢了一个数量级。 如果你从当前线程同步调用一个函数,最好使用const&版本。
其他回答
就我个人而言,我会使用const引用。没有必要为了函数调用而增加引用计数。
众所周知,通过值传递shared_ptr是有代价的,应该尽可能避免。
通过shared_ptr传递的代价
大多数情况下,通过引用传递shared_ptr,甚至更好的是通过const引用。
cpp核心准则有一个传递shared_ptr的特定规则
R.34:接受shared_ptr参数来表示函数是部分所有者
void share(shared_ptr<widget>); // share -- "will" retain refcount
当调用方将一个共享对象传递给异步被调用方时,即调用方在被调用方完成其工作之前就超出了作用域,这就是按值传递shared_ptr确实必要的一个例子。被调用方必须通过取share_ptr值来“延长”共享对象的生存期。在这种情况下,传递对shared_ptr的引用是不行的。
将共享对象传递给工作线程也是如此。
通过const引用传递,它更快。如果你需要存储它,比如在某个容器中,引用计数将通过复制操作自动神奇地增加。
最近有一篇博客文章:https://medium.com/@vgasparyan1995/pass-by-value vs-pass-by-reference-to-const-c-f8944171e3ce
所以这个问题的答案是:Do(几乎)从不传递const shared_ptr<T>&。 只需传递底层类即可。
基本上,唯一合理的参数类型是:
shared_ptr<T> -修改并获得所有权 shared_ptr<const T> -不修改,拥有所有权 T& -修改,没有所有权 const T& -不修改,没有所有权 T -不修改,没有所有权,廉价复制
正如@accel在https://stackoverflow.com/a/26197326/1930508中指出的,Herb Sutter的建议是:
只有在不确定是否获得副本和共享所有权时,才使用const shared_ptr&作为参数
但有多少情况下你不确定?所以这种情况很少见
Shared_ptr不够大,它的构造函数\析构函数也没有做足够的工作,因此拷贝有足够的开销来关心按引用传递和按复制传递的性能。