標籤:

常量字元串是右值,為什麼沒有調用相應的右值重載函數?

vector& vString;
vString.push_back("aaa"); // 1
vString.push_back(string("bbb")); // 2

1調用的是void push_back(const _Ty _Val)。

2調用的是void push_back(_Ty _Val)。

1,2調用的字元串構造函數是相同的,感覺應該都是右值才是啊,為什麼1沒有調用右值的push_back函數呢?

環境是VS2010。

彙編,未優化.


現行標準下,兩種寫法是等效的。但是VS2010發佈於2010年,右值引用的語義在那之後又有發展。

VS2010支持的右值引用語義對應的是v2.0(N2844)。這個提案中禁止了右值引用綁定到左值的情況。臨時構造的對象是右值,可以綁定到右值引用,但在這個提案中明確要求了初始化表達式(也就是本題中構造函數的參數)必須為右值

需要注意的是與一般字面量不同,字元串常量是左值,因為其代表字元數組。在N2844提案下使用左值構造的臨時對象不能綁定右值引用。如果使用一般的字面量(右值)構造臨時對象其實是可以綁定右值引用的。

struct IntVal
{
IntVal(int) {}
};

int main()
{
vector& v;
v.push_back(42); // push_back(_Ty _Val)
v.push_back(IntVal(42)); // push_back(_Ty _Val)
return 0;
}

這個問題到2010年8月時提出,10月的標準草案(N3225)中刪除了初始化表達式為右值的要求,這樣左值構造的臨時對象也可以綁定到右值引用,在MSDN上稱為v2.1,VS2012實現了這個語義。

參考:Support For C++11/14/17 Features (Modern C++)


@Felix Qiu 的答案正解了。我就想來跑個題說其實vector有新的emplace_back()函數更好用。

STL大大教的:Don"t Help the Compiler(打不開請自備工具),14:15左右開始的地方。

(是Stephan T. Lavavej大大喔)


A literal is a primary expression. Its type depends on its form (2.13). A string literal is an lvalue; all other

literals are prvalues. ----------N4582


誰告訴你字元串常量不是左值啦,明明就是左值。。

字元串常量的類型是const char [N],N是長度(含末尾),數組嘛,const左值


我在vs2015上測試了一下,會先調用std::string的構造函數構造出std::string,然後再調用push_back(_Ty val),根據Overload resolution,也應該是這樣。

所以一切的問題都應該歸罪於vs2010的bug


因為常量字元串實際上就是const char*。

自然不會被非const的匹配到啦。


親測,兩個都調用右值版本。我用的是vs2015社區版


根據我的理解說吧,常量不能轉化成非常量,所以字元串常量就只能匹配第一個了。


我用VS2015調用的都是右值,VS版本的問題?


能提供反彙編代碼嗎?

release不優化下能看。

rug確實反彙編release未優化工程的話,我承認我看不懂。

如果是C,我勉強能看懂。。

所以,答主試試試試?

匿了


推薦閱讀:

你有什麼關於Linux下C++並行編程的好書和經驗跟大家分享?
為什麼 C++ 中,基類指針可以指向派生類對象?
在取消同步的情況下,為什麼cin的速度比scanf快?
GCC編譯的程序為什麼沒有正確調用拷貝構造函數?

TAG:C | C11 |