当一个函数接受一个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) ?
我更喜欢第一种方法,因为我怀疑它会更快。但这真的值得吗,还有其他问题吗?
你能否给出你选择的原因,或者如果是这样,为什么你认为这无关紧要。
当前回答
Shared_ptr不够大,它的构造函数\析构函数也没有做足够的工作,因此拷贝有足够的开销来关心按引用传递和按复制传递的性能。
其他回答
由于不知道shared_copy复制操作的时间成本,我遇到了更高的CPU使用问题。我从来没有想到原子增量和减量会付出这么大的代价。
根据我的测试结果,int32原子增量和减量比非原子增量和减量需要2倍或40倍的时间。我用的是3GHz Core i7, Windows 8.1。前者在不发生争用时得出,后者在发生争用可能性较大时得出。我始终牢记原子操作是基于硬件的锁。锁就是锁。发生争用时对性能不利。
遇到这种情况,我总是使用byref(const shared_ptr&)而不是byval(shared_ptr)。
就我个人而言,我会使用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的引用是不行的。
将共享对象传递给工作线程也是如此。
Scott、Andrei和Herb在c++ and Beyond 2011的Ask Us Anything会议上讨论并回答了这个问题。从4:34开始观看shared_ptr的性能和正确性。
简单地说,没有理由按值传递,除非目标是共享对象的所有权(例如:共享对象的所有权)。不同的数据结构之间,或不同的线程之间)。
除非你可以像Scott Meyers在上面链接的演讲视频中解释的那样对它进行移动优化,但这与你可以使用的实际c++版本有关。
这个讨论的主要更新发生在GoingNative 2012会议的互动小组:问我们任何事情!值得一看,尤其是22:50开始。