关于静态变量的C++参考

use*_*468 15 c++ static reference

我只是发现这个小小的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;
}
Run Code Online (Sandbox Code Playgroud)

使用clang ++它写道:

aaaaaaaaa zzzzzzzzzz

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

aaaaaaaaa aaaaaaaaa

为什么会这样?g ++实现标准是否合规?如果我想要一个函数通过像这样的引用返回一个临时的"大"类型,以避免无用的副本,我该怎么办?

NPE*_*NPE 23

是的,两种实现都是兼容的.未指定函数参数的评估顺序.

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

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

最后,值得注意的是,拥有static状态将是多线程环境中的一个主要问题.

  • 确实.允许编译器在调用`operator <<()`之前生成对`createString()`的调用(如g ++显然那样),或者散布它们(就像clang ++正在做的那样).所以它是相对的顺序所有这些重要的函数调用. (4认同)
  • 它不是`createString('a')`和`createString('z')`的顺序,而是它们与导致意外行为的`<<`运算符的相对顺序. (3认同)
  • @MarkRansom我不认为`zzzzzzzzzz aaaaaaaaaa`是一个合法的输出.`createString('z')`当然可以在`createString('a')`之前运行,但是`createString('a')`必须仍然在第一个`operator <<之前运行.因此,如果'z'先运行,那么输出必须是'aaaaaaaaa aaaaaaaaaa',如果'a'先运行,那么输出可以是'aaaaaaaaaa zzzzzzzzzz`或`zzzzzzzzzz zzzzzzzzzz`. (3认同)

Pup*_*ppy 7

如果我想要一个函数通过像这样的引用返回一个临时的"大"类型,以避免无用的副本,我该怎么办?

它不会.RVO和NRVO可以轻而易举地解决这个问题.另外,移动语义.简而言之,返回一个std::string按值完全没什么问题.