2013-01-18 28 views
5

聲明:這個問題是爲了理解。我將在現場使用boost::lexical_castIt has sort of come up in the real world in places, though.這是一個引用到非const綁定到臨時的實例嗎?


採取the following attempt在「內聯」法鑄方法:

#include <string> 
#include <sstream> 
#include <iostream> 

int main() 
{ 
    const std::string s = static_cast<std::ostringstream&>(
     std::ostringstream() << "hi" << 0 
    ).str(); 
    std::cout << s; 
} 

的結果是一樣的東西0x804947c0,因爲與"hi"工作的operator<<是一個免費的功能,其LHS必須採取std::ostream&&dagger;,臨時std::ostringstream()無法綁定到ref-to-non- const。唯一剩下的匹配是operator<<,需要const void*對RHS &dagger;&dagger;

現在let's swap the operands

#include <string> 
#include <sstream> 
#include <iostream> 

int main() 
{ 
    const std::string s = static_cast<std::ostringstream&>(
     std::ostringstream() << 0 << "hi" 
    ).str(); 
    std::cout << s; 
} 

結果是"0hi"

這主要是有道理的,因爲這需要intoperator<<是鹼ostream&匕首的成員函數;&匕首;&匕首;,因此,在臨時調用時可以。該操作的結果是對ostream基礎的引用,將下一個operator<<鏈接到該基礎,即將其作爲(std::ostringstream() << 0) << "hi"來讀取。

但是爲什麼然後運行在"hi"繼續產生預期的結果? LHS上的參考文獻還不是暫時的嗎?


讓我們專注於C++ 03;我被告知第一個例子實際上可能在C++ 11中作爲「預期」工作,因爲rvalues的catch-all操作符。

&dagger;[C++03: 27.6.2.1]: template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,charT*);

&匕首;&匕首;[C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(const void* p);

&匕首;&匕首;&匕首;[C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(int n);

+0

我想答案是沿着「將臨時參照物綁定到引用的規則遠不是那麼簡單的規則;這裏是相關的短語」。 –

+0

這與您可以編寫函數模板'template T&lvalue(T && v){return v;}'以將非常量左值引用綁定到臨時對象的原因相同。 – Mankarse

+0

第一個腳註的重載不會是那些採用const char [T] *'的腳本嗎? (不是說它改變了什麼。) – Mat

回答

3

原因很簡單。如果你讀了問題,我問:

std::ostringstream printing the address of the c-string instead of its content.

你會注意到,招得到一個「適當」引用,而不是一個臨時的方法是調用對象的方法(沒有限制到某些原因沒有約束力的限制),這將返回一個引用。

在謝里夫的回答上面,他叫std::ostream& std::ostream::flush(),你的情況在這裏:

std::ostringstream() << 0 << "hi" 

你打電話std::ostringstream& std::ostringstream::operator<<(int)

相同的結果。

令人驚訝的行爲是由於ostream mishmash實現:一些operator<<是成員方法,而其他一些是自由函數。

您可以測試它,簡單地說,通過在物體上實現一個X& ref()方法:

struct X { X& ref(); }; 

void call(X& x); 

int main() { 
    call(X{});  // error: cannot bind X& to a temporary 
    call(X{}.ref()); // OK 
} 

編輯:但爲什麼不X&(的ref結果)同等對待?

這是一個classification的問題。臨時是prvalue,而參考是lvalue。參考僅允許綁定到lvalue

當然因爲方法可以在rvalue(因此prvalue)被調用,這些方法可以返回到它們被稱爲上我們的對象的引用可以很容易地繞過傻(1)的引用僅被允許結合於一個lvalue限制...

(1)它也不符合rvalue可以綁定到const引用的事實。

+1

我不認爲這回答了這個問題。我知道成員函數和自由函數。但是這個對象仍然是一個臨時對象,那麼爲什麼引用最終會綁定到它,因爲它是由函數調用產生的呢? –

+0

@LightnessRacesinOrbit:一個簡單的'lvalue' /'rvalue'問題,我擴展了我的答案。編譯器如何知道'X&X :: ref()'是調用'ref'的一個'X'實例?它不能(一般),所以它完全基於類型的分類。 –

+0

編輯做到了;謝謝 –

2

是不是在LHS參考還是一個臨時的?

它是一個左值引用臨時(返回值),它仍然是一個左值,因此可以綁定到左值引用。在壽命,而不是升/ rvalueness方面的臨時的

思考。

+0

(你可能知道這個,我對你在問什麼感到困惑:S) – Pubby

相關問題