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::stringby 値を返すことに問題はまったくありません。

于 2013-03-15T15:35:43.370 に答える
2

そして、役に立たないコピーを避けるために、ここのように関数が参照によって一時的な「大きな」型を返すようにしたい場合はどうすればよいですか?

式ごとに 1 回だけ呼び出します。たとえば、これはうまくいきます:

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