构造函数中按值传递std::string的性能探讨
现代C++中值传递string参数的性能分析
先看给定的类定义:
class MyClass { public: MyClass(std::string str) : m_str(std::move(str)) {} private: std::string m_str; };
核心结论
这种写法绝不会在任何情况下比const引用传递效率更低,反而在多数场景能拿到最优性能——对于支持移动语义、仅需将参数复制到成员变量且不在构造函数其他地方使用的场景,值传递+std::move的写法总能获得最优或持平的性能表现。
分场景性能对比
1. 传入临时字符串(如字面量、返回string的函数结果)
比如调用MyClass("hello world")或者MyClass(get_some_string()):
- 编译器可以通过复制消除(RVO/NRVO)直接把临时字符串构造到函数参数
str的内存位置,随后通过std::move把str的内容转移到成员m_str。全程只有一次字符串构造+一次无代价的移动操作,没有任何复制。 - 如果改用
const std::string&传参,构造函数内部必须执行m_str = str完成一次复制,多了一次昂贵的内存分配和数据拷贝,效率明显更低。
2. 传入左值字符串(如已存在的string变量)
比如调用std::string s = "test"; MyClass(s);:
- 值传递会先复制一次
s到参数str,再通过std::move转移到m_str,总共有一次复制+一次移动。 - 用
const std::string&传参的话,构造函数内部直接复制s到m_str,是一次复制。 - 两者的核心复制次数完全相同,而
std::move的代价极低(仅转移指针和几个整数成员),可以忽略不计,因此性能几乎没有差异。
对复制消除的补充
你提到的复制消除逻辑完全正确:
- 若编译器未执行复制消除,值传递的复制操作发生在调用前,const引用的复制发生在构造函数内,总复制次数都是1次,性能持平。
- 若编译器执行了复制消除,值传递写法直接跳过复制,仅用一次move完成成员初始化,比const引用写法更高效。
内容的提问来源于stack exchange,提问作者DaedalusAlpha
相关产品推荐
相关产品推荐

