考虑以下代码:
void doSomethingWithString(string& mString)
{
// mString gets modified in here
}
string getCopy1(const string& mString)
{
string result{mString}; doSomethingWithString(result); return result;
}
string getCopy2(string mString)
{
doSomethingWithString(mString); return mString;
}
在getCopy1
和getCopy2
之间,是什么:
答案 0 :(得分:4)
两个版本都清楚地表明没有修改传入值的意图。
在将rvalue作为参数传递的情况下, getCopy2
更有效。在这种情况下,不需要复制,因为参数将被移动而不是复制,并且您不进行内部复制。对于getCopy1
,您始终强制至少制作一份副本。如果将左值作为参数传递,则需要执行移动而不是创建引用。哪个更有效取决于编译器的大量细节和字符串实现,但移动的速度应该与创建引用的速度相当。
就返回值而言,我认为没有任何区别。
答案 1 :(得分:3)
在getCopy1和getCopy2之间,有哪一个:
- 清楚地显示传递的字符串不会被修改
两者:首先,因为虽然它需要引用,但引用是const
;第二,因为它创建了自己的副本。
- 清楚地显示用户将返回新的字符串
两者:它们都返回一个字符串实例;
- 编译器更快/可以更好地优化(启用C ++ 11,考虑移动语义)
第二种更好用:如果你要复制输入参数,最好在参数本身中做(最好让编译器在调用时复制);它也更好,因为在rvalue引用的情况下,没有额外的副本完成。
答案 2 :(得分:2)
getCopy2
通常可以更好地进行优化。这在"Want Speed? Pass by Value."
答案 3 :(得分:2)
在Linux Mint x64上使用G ++ 4.8.1进行一些测试。
标志:-std=c++11 -O3 -DNDEBUG
void doSomethingWithString(string& mString) { mString[0] = 'f'; }
string getCopy1(const string& mString)
{
string result{mString}; doSomethingWithString(result); return result;
}
string getCopy2(string mString)
{
doSomethingWithString(mString); return mString;
}
int main()
{
string s{"132958fdgefi9obm3890g54"};
string t{""};
{
startBenchmark();
for(int i{0}; i < 20000000; ++i) t = getCopy1(s);
log(endBenchmark(), "getCopy1 variable");
}
{
startBenchmark();
for(int i{0}; i < 20000000; ++i) t = getCopy1("abcsd");
log(endBenchmark(), "getCopy1 literal");
}
{
startBenchmark();
for(int i{0}; i < 20000000; ++i) t = getCopy2(s);
log(endBenchmark(), "getCopy2 variable");
}
{
startBenchmark();
for(int i{0}; i < 20000000; ++i) t = getCopy2("abcsd");
log(endBenchmark(), "getCopy2 literal");
}
return 0;
}
输出:
[getCopy1 variable] 1236 ms
[getCopy1 literal] 1845 ms
[getCopy2 variable] 993 ms
[getCopy2 literal] 857 ms
结论:
getCopy2
更快,特别是对于rvalues(文字字符串)。