1

考虑这段代码:

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,是什么:

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

?

4

4 回答 4

4

任何一个版本都清楚地表明没有意图修改传入的值。

getCopy2在将右值作为参数传递的情况下效率更高。在这种情况下,不需要进行复制,因为参数将被移动而不是复制,并且您没有进行内部复制。对于getCopy1,您总是强制至少制作一份副本。如果将左值作为参数传递,则需要进行移动而不是创建引用。哪个更高效取决于编译器和字符串实现的很多细节,但移动的速度应该与创建引用的速度相当。

就返回值而言,我没有看到任何区别。

于 2013-06-10T13:33:54.797 回答
3

在 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更快,尤其是右值(文字字符串)。

于 2013-06-10T13:43:27.873 回答
3

在 getCopy1 和 getCopy2 之间,是什么:

  • 清楚地表明传递的字符串不会被修改

两者:首先,因为虽然它需要一个引用,但引用是const; 其次,因为它创建了自己的副本。

  • 清楚地表明用户将得到一个新的字符串返回

两者:它们都返回一个字符串实例;

  • 更快/编译器可以更好地优化(启用 C++11,考虑移动语义)

第二种更好用:如果要复制输入参数,最好在参数本身中进行(最好让编译器进行复制,随叫随到);这也更好,因为在右值引用的情况下,没有额外的复制。

于 2013-06-10T13:36:26.837 回答
2

getCopy2通常可以更好地优化。这在“想要速度?传递价值”中得到了巧妙的解释。

于 2013-06-10T13:42:53.307 回答