如何初始化std::shared_ptr成员?两种方式的性能对比
两种初始化方式
以下两种方式都会增加std::shared_ptr的引用计数:
1. 传递const引用(兼容左值与临时对象)
最初的版本仅支持左值引用,无法直接接收std::make_shared创建的临时对象,更新为const引用后可同时兼容两种场景:
class MyClass { std::shared_ptr<std::string> s1; public: MyClass(const std::shared_ptr<std::string>& s2): s1{s2} {} };
2. 传递值并移动
通过传值构造参数,再利用std::move将参数转移到成员变量中:
class MyClass2 { std::shared_ptr<std::string> s1; public: MyClass2(std::shared_ptr<std::string> s2): s1{std::move(s2)} {} };
基础引用计数验证
测试两种方式对引用计数的影响:
int main() { std::shared_ptr<std::string> s2 = std::make_shared<std::string>("Hello World"); MyClass myClass {s2}; MyClass2 myClass2 {s2}; std::cout << "Use count:" << s2.use_count() << std::endl; return 0; }
测试结果:
Use count:3
两种方式均会使引用计数+1,最终s2的引用计数为自身、MyClass成员、MyClass2成员三者之和。
性能对比疑问
第二种方式多了一次移动操作,看起来没有优势,那从性能角度出发,哪种初始化方式更优?
大规模循环基准测试
在千万次循环场景下验证性能差异:
#include <iostream> #include <memory> #include <chrono> using namespace std; class MyClass { std::shared_ptr<std::string> s1; public: MyClass(const std::shared_ptr<std::string>& s2): s1{s2} {} }; class MyClass2 { std::shared_ptr<std::string> s1; public: MyClass2(std::shared_ptr<std::string> s2): s1{std::move(s2)} {} }; int main() { std::shared_ptr<std::string> s2 = std::make_shared<std::string>("Hello World"); auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 10000000; i++) { MyClass myClass {s2}; } auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<float> duration = end - start; std::cout << duration.count() << std::endl; start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 10000000; i++) { MyClass2 myClass2 {s2}; } end = std::chrono::high_resolution_clock::now(); duration = end - start; std::cout << duration.count() << std::endl; return 0; }
测试结果(C++17在线编译器)
0.358915 0.623789
结论
从测试结果可明确看出,传递const引用的方式性能更优。原因在于:
- 传const引用初始化时,仅需执行一次引用计数的原子递增操作;
- 传值再移动的方式,首先要对左值参数执行一次拷贝(原子递增引用计数),再执行移动操作(虽轻量但仍有额外开销),整体开销高于直接传引用。
当然传值方式并非完全无用:若需同时支持左值、右值传入且避免重复重载函数,可考虑传值再移动,但仅处理左值的场景下,传const引用的性能优势是明确的。
内容的提问来源于stack exchange,提问作者Metropol_Tilkisi
相关产品推荐
相关产品推荐

