15

我只是发现这段 C++ 代码并没有给我与 clang++ 和 g++ 相同的结果:

#include <iostream>
#include <string>

using namespace std;

const string& createString(char c) {
    static string s;
    s="";
    for(int i=0; i<10; ++i) {
    s+=c;
    }
    return s;
}

int main() {
    cout << createString('a') << ' ' << createString('z') << endl;
    return 0;
}

使用 clang++ 它写道:

啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

就像我想要的那样,但是使用 g++ 它写道:

啊啊啊啊啊啊啊啊

为什么会这样?是否符合 g++ 实现标准?如果我想让一个函数像这里一样通过引用返回一个临时的“大”类型以避免无用的复制,我该怎么办?

4

3 回答 3

23

是的,两种实现都是合规的。未指定函数参数的评估顺序。

因此,createString('a')并且createString('z')可以按任何顺序进行评估。此外,可以在写出createString('z')结果之前或之后进行评估。createString('a')

由于该函数是有状态的,并通过引用返回状态,因此两个输出都是允许的,就像zzzzzzzzzz zzzzzzzzzz.

最后,值得注意的是,static在多线程环境中,拥有状态将是一个令人头疼的问题。

于 2013-03-15T15:30:43.407 回答
7

如果我想让一个函数像这里一样通过引用返回一个临时的“大”类型以避免无用的复制,我该怎么办?

不会的。RVO 和 NRVO 可以轻松解决这个问题。此外,移动语义。简而言之,std::string按值返回 a 根本没有问题。

于 2013-03-15T15:35:43.370 回答
2

如果我想让一个函数像这里一样通过引用返回一个临时的“大”类型以避免无用的复制,我该怎么办?

每个表达式只调用一次。例如,这将正常工作:

std::cout << createString('a') << ' ';
std::cout << createString('z') << std::endl;
于 2013-03-15T16:03:45.123 回答