2017-06-01 81 views
6

因此我知道s2綁定到表達式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將產生一個臨時std::string,這將被綁定到參考s2(及其壽命延長到參考的壽命)。然後s2 += "Test";,在s2上執行operator+=(),即臨時std::string

+0

感謝您的快速回復。看起來,如果's2'只是另一個'std :: string',結果將是相同的,但是結果二進制文件會有什麼不同? –

+0

@BradyDean是的結果是一樣的。關於結果二進制文件很難說;無論如何,我試過[這裏](https://gcc.godbolt.org/),它給了同樣的程序集。 – songyuanyao

+0

請注意,這種情況在C++ 17中發生了變化,在這種情況下,可觀察到的差異爲零。 – Yakk

2

表達式總是在程序到達它們的時候進行評估。表達式的結果總是一個值(或無效)。

值有一個類型,表達式有一個值類別,它可以組合使用任何特定用途的過載集合的重載。

在你的情況下,string operator+(...)產生一個字符串值,帶有類別pr值(這是一種右值)。然後它立即綁定到一個字符串& &,所以它的生命週期延伸到參考的壽命。

如果您改爲將其分配給一個純字符串,那麼string& string::operator=(string&&)將被選擇爲該運算符的任何其他重載。請注意,由於C++ 11允許編譯器(並且需要C++ 17)直接在目標對象內實現該值。此過程稱爲複製/移動省略或(N)RVO,用於(命名)返回值優化。

+0

@Yakk哪些東西特別重要?據我所知,唯一的變化就是移動的構造被忽略了,這與C++ 14的字符串 – Caleth

+1

沒有明顯的不同。對不起,我發誓我看到了「物體」這個詞,它不應該是這個詞,但我現在沒有看到它,所以我一定是錯的。 – Yakk