“std :: string”或“const std :: string&”争论? (该参数在内部复制和修改)

时间:2013-06-10 13:01:43

标签: c++ string c++11 reference parameter-passing

考虑以下代码:

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; 
}

getCopy1getCopy2之间,是什么:

  • 清楚地显示传递的字符串不会被修改
  • 清楚地显示用户将返回新的字符串
  • 编译器更快/可以更好地优化(启用C ++ 11,考虑移动语义)

4 个答案:

答案 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(文字字符串)。