2017-06-01 22 views
6

は式s1 + s1に結びついていますが、これはs2が割り当てられたときに評価されるか、s2 += "Test";が呼び出されたときに怠けて評価されています。また、s2は一時的な文字列のためにメモリを保持しますか?評価値はいつ評価されますか?

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string s1 = "Test"; 
    std::string&& s2 = s1 + s1; 
    s2 += "Test"; 
    std::cout << s2 << '\n'; 
} 

答えて

16

s2表現s1 + s1に結合するが、これは時間s2で評価されるがはい

が割り当てられます。

また、s2は一時的な文字列のためのメモリを保持しますか?

正確には、s2は、一時的なstd::stringに結びついています。

s1 + s1は、参照番号s2(およびその有効期間は参照の有効期間まで延長されます)にバインドされる一時的なstd::stringを生成します。次にs2 += "Test";は、s2operator+=()を実行します。つまり、一時的なstd::stringです。

+0

クイック返信ありがとうございます。 's2'がちょうど別の' std :: string'だったとしたら、結果は同じになりますが、結果のバイナリは違うでしょうか? –

+0

@BradyDeanはい、結果は同じです。結果のバイナリについて言うのは難しいです。とにかく私はそれを試してみた(https://gcc.godbolt.org/)、それは同じアセンブリを与えた。 – songyuanyao

+0

これは、このケースでは観測可能な差異がゼロになるような方法でC++ 17で変更されています。 – Yakk

2

式は、プログラムが到達した時点で常に評価されます。式の結果は常に値(またはvoid)です。

値には型があり、式には値のカテゴリがあり、これを組み合わせることで、特定の用途でオーバーロードセットのどのオーバーロードを使用するかを選択できます。

あなたのケースでは、string operator+(...)は、カテゴリpr-value(rvalueのタイプ)で、文字列値になります。それはすぐに文字列& &にバインドされています。そのため、参照の寿命まで延長されています。

代わりにプレーンストリングに割り当てた場合は、その演算子の他のオーバーロードよりもstring& string::operator=(string&&)が選択されています。 C++ 11以来、コンパイラはターゲットオブジェクトの中の値を直接実体化することができます(そしてC++ 17が必要です)。このプロセスは、(名前付き)戻り値最適化のためのコピー/移動エリジョンまたは(N)RVOとして知られています。

+0

@ヤク特にどちらのこと?私の知る限りでは、唯一の変更は、移動の構築が省略され、それはC++ 14の文字列とはまったく異なっていないということです。 – Caleth

+1

申し訳ありませんが、私は "オブジェクト"私は今それを見ていないので、私は間違っている必要があります。 – Yakk