函数实参传递:右值引用与const左值引用的效率对比
关于两种字符串传递方式的效率分析
咱们先把这个问题拆开来聊,首先得纠正一个容易混淆的点,再一步步分析效率差异:
1. 先澄清参数传递阶段的误区
你提到的「拷贝构造/移动构造」其实不会发生在参数传递这一步,咱们具体看:
- 对于
processString1(const string & str):传入字符串字面量"Hello"时,编译器会先临时构造一个std::string对象(从const char*字面量转换而来),然后这个临时对象直接绑定到const string&引用上——引用只是给已有对象起别名,不需要创建新字符串,所以这一步没有拷贝/移动开销。 - 对于
processString2(string && str):同样,编译器先构造临时std::string对象,再把这个临时右值绑定到string&&引用上——还是单纯的绑定操作,没有拷贝或移动构造。
2. 真正体现效率差的场景:函数内部需要保存字符串副本
你说的拷贝/移动构造,应该是指函数内部要把传入的字符串存为本地副本的情况,比如:
// processString1 内部保存副本 void processString1(const string & str) { string internal_str = str; // 这里调用拷贝构造函数 } // processString2 内部保存副本 void processString2(string && str) { string internal_str = std::move(str); // 这里调用移动构造函数 }
这时候差异就非常显著了:
- 拷贝构造:
std::string的拷贝构造需要重新分配内存,把原字符串的所有字符逐一复制,时间复杂度是O(n)(n为字符串长度),内存开销大。 - 移动构造:
std::string的移动构造只是把原对象内部的字符数组指针、长度、容量等成员直接“转移”给新对象,原对象变为空状态,整个过程是O(1)的常数时间,几乎没有开销。
3. 最终结论
- 如果函数只是读取传入的字符串,不需要保存副本:两种传递方式效率几乎无差别,都是绑定临时对象,没有额外开销。
- 如果函数需要保存传入字符串的副本:
processString2这种右值引用配合移动构造的方式,效率远高于processString1的左值引用+拷贝构造。
内容的提问来源于stack exchange,提问作者michalt38
相关产品推荐
相关产品推荐

