2012-07-16 46 views
10

在Visual Studio 2012RC中有一些非標準的擴展。例如,此代碼彙編:左值轉換左值Visual Studio

#include <string> 

using namespace std; 

void value(string& value) 
{ 
    value = "some"; 
} 

int main() 
{ 
    value(string("nice")); 
} 

並得到警告,它是非標準的擴展名。所以,我想了解,它是如何真實的以及代碼如何轉換(使用const_cast的右值引用或const引用)?

+1

AFAIK,Visual Studio 2010(也許2008)也支持這種行爲。 VC++編譯器允許修改臨時對象。 – flamingo 2012-07-16 16:39:23

+0

請注意,這是最糟糕的風格,最壞的情況下容易出錯([「你不關心它是你正在修改的臨時版嗎?」)(http://stackoverflow.com/a/1565811/768469)) – Nemo 2012-07-16 16:59:19

+1

@火烈鳥:那麼,修改C++中的臨時對象從來就不是非法的。它始終被允許在C++中調用非const *修飾*臨時對象的成員函數。然而,使用「直接」語法附加非const引用是非法的。如我的答案所示,前者實際上允許人們繞過後者。 – AnT 2012-07-16 17:04:04

回答

8

類類型的臨時對象仍然是一個對象。它居住在內存的某個地方,這意味着在編譯器中沒有任何異常可以附加引用。在物理層面,無論是const引用還是非const引用都沒有區別。換句話說,在這種情況下,語言限制純粹是概念性的,人爲的。編譯器只是忽略這個限制。沒有必要在這裏「轉換」任何東西。該引用直接附加到該對象,無論該對象恰好駐留在哪裏。

基本上,對於提供與訪問其this指針的值的外字一個類(或左值訪問*this)的行爲可以是立即和容易地模擬

struct S { 
    S& get_lvalue() { return *this; } 
}; 

void foo(S& s); 
... 

foo(S().get_lvalue()); 

上面的代碼是完全合法,它圍繞上述限制。您可以將MSVC++行爲視爲與此等效。

+0

謝謝。有趣。公認。 – ForEveR 2012-07-16 16:55:06

+1

如果我們在功能之外存放暫時存儲器,這是否會導致UB? – Guillaume07 2013-04-15 08:01:42

+0

@ Guillaume07:你可以重述嗎?我不明白「股票」是什麼意思。 – AnT 2013-04-16 18:48:22

3

基本上,VS將某處分配的空間,只是讓參考點到它,彷彿它是一個基準TO- const而不常量性(或者在C++ 11一個rvalue參考)。

您可以在

屬性禁用與/Za(禁用語言擴展)編譯器開關這種行爲 - > C/C++ - >語言

如果我沒有記錯。

+0

謝謝。好答案。接受,但啓用/ ZA很糟糕,因爲任何正確的代碼都不會編譯(在C++ 11下)。 – ForEveR 2012-07-16 16:44:03

+0

不接受,因爲AndreyT的答案更有用 – ForEveR 2012-07-16 16:57:44

3

在標準C++中,您不能將臨時(右值/ string("nice"))綁定到非常量引用(左值),但Microsoft編譯器允許它。該警告告訴你,代碼由於擴展而編譯,並且不會與任何其他編譯器一起編譯。