標籤:

C++為什麼允許s1+s2="D";這種語句?

s1,s2都是string。

在C++ Primer上看到的,它說新標準可以避免這種情況…

可是為什麼會允許給右值賦值…求解…


在C++裡面,並不一定只有左值才能調用operator=的。對於所有自定義類型,只要不是const,就可以用Operator=


人家明明在左邊……

~~~ 好吧,以下是迷惑的來源 ~~~

題主的思路大致應該是這樣的:

C++03 §5.2.2/10

A function call is an lvalue if and only if the result type is a reference.

歌詞大意:函數調用表達式的值是什麼值,要看情況:

  • 返回引用:左值
  • 返回其它:右值

所以 s1 + s2 確實是個右值呀。

C++03 §5.17/1

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue with the type and value of the left operand after the assignment has taken place.

歌詞大意:等號左側一定要是可修改的左值。

s1 + s2 = "D" 左邊應該是左值呀,所以很矛盾呀。

看上去很有道理不是嗎?但是,之所以 s1 + s2 = "D" 可行,是因為:

C++03 §5/3

Clause 5 defines the effects of operators when applied to types for which they have not been overloaded. Operator
overloading shall not modify the rules for the built-in operators, that is, for operators applied to types for which they are
defined by this Standard. However, these built-in operators participate in overload resolution, and as part of that process
user-defined conversions will be considered where necessary to convert the operands to types appropriate for the built-
in operator.

歌詞大意:本章內容只對內置操作符有效

std::string::operator=() 不是內置操作符,而是重載……(通俗地說:逗你玩兒~)


vector& v;

v.push_back(true);

v[0] = false; // 這句和s1 + s2 = "xxx";有區別嗎?

==========================

因為有人質疑,於是補充一下:

注意,vector&是vector的一個特化實現,和普通的vector不同,它使用一個bit來表示一個bool值,而非直接用的bool數組來存儲的。

v[0]返回的是一個臨時對象,這個臨時對象中有一些信息標識了這是vector中的第幾個元素,然後重載了operator bool和operator=,用來讓這個臨時變數用起來和一個bool一樣。


其實即使是const, 也可能可以用operator=(),只要足夠賤,C++隨便玩兒……比如下面:

#include &

class TestClass {

public:

mutable int b_;

TestClass(int b):b_(b) {};

void operator=(int a) const {b_ = a;};

};

using namespace std;

int main(){

const TestClass tc(1);

tc = 3;

cout &<&< tc.b_ &<&< endl;

return 0;

}


我也來舉個栗子吧。

下邊的程序會編譯錯誤:

int foo() {
int a = 0;
return a;
}

int main() {
--foo();
return 0;
}

原因是--只能用於左值。

然而下邊的程序卻不會編譯錯誤:

int main() {
set& s;
s.insert(1);
s.erase(--s.end());
return 0;
}

因為這裡--被重載了,作用於一個臨時對象。


因為有運算符重載。

就像你調用

s1.Plus(s2).Assign("D");

一樣。


這是s1+s2產生的臨時對象再調用string類的成員函數operator=,c++標準里又沒說右值不能調用成員函數。


代碼貼全一點吧

string s1, string s2;
s1+s2="D";

這裡應該是調用了string的operator+操作符, 它返回的是一個臨時變數, 不是返回右值

相當於是

string s3 = s1 + s2;
s3 = "D";


推薦閱讀:

什麼時候應當依靠返回值優化(RVO)?
認真學完 C++ Primer 後,C++ 語言到了什麼水平?
為什麼C++編譯器不能發現未初始化的變數?
數據結構課本中的「生命遊戲」有哪些奇葩的玩法?
如何理解《Effective C++》第31條將文件間的編譯依賴關係降低的方法?

TAG:C |