第四章:表達式

一:左值和右值

        這個概念暫時很模糊,打算學完這一章再總結。目前的理解是,左值有名字,可以通過名字訪問內存,右值沒有名字,一般是運算的中間結果或者字面值常量等。

        const修飾的變量是常量左值

        如果decltype()函數的括號中表達式結果是左值,則得到一個引用類型。例如在下面這段代碼中,b是int類型,c是int*類型

	int a;
	decltype(a) b;
	decltype(a = 0) c = a

二:神奇的求值順序(以前沒注意到耶)

int i = 0;
cout << i << " " << ++i << endl;

        輸出是1 1,沒想到吧哈哈。其實1,1這個答案是沒意義的,也就是說,對於運算符"<<",其運算對象的執行順序是不可預測的,像這裏不是先輸出左側的i,而是先執行++i操作。同樣,對於int a = f1() + f2();先調用f1()還是先調用f2()是不固定的,因爲加法沒有規定運算對象的執行順序鴨。

        只有四種運算符規定了執行順序:邏輯與(&&)運算符,邏輯或(||)運算符,條件(? :)運算符,逗號( , )運算符。

        上圖是再次強調求值順序的陷阱,小心寫出了錯誤的代碼。

        編譯器之所以沒有規定求值順序,是爲編譯器的優化提供了餘地。

三:c++11標準規定的除法和取餘規則

        設m,n都是整數,則(-m)/n =m/(-n) = - (m/ n);  m/n = (-m)/(-n) ; (-m)%n = (-m)%(-n) = -(m%n), m%n = m%(-n) 

四:賦值運算符

        賦值運算是右結合的。

五:遞增和遞減運算符

        ++i是前置版本,i++是後置版本。前置版本返回的是修改後的對象,作爲左值,後置版本將對象修改前的副本作爲右值返回。由於後置版本需要保存原始值的副本,所以性能會較低,建議養成使用前置版本的習慣鴨。

	int i = 0;
	++i = 3;
	//i++ = 3;
	cout << i << endl;
	while (1){}
	return 0;

        在上面這段代碼中,輸出值是3,這是因爲++i = 3這句代碼將3賦值給了對象i 。但是註釋的部分i++ = 3的語句是不合法的,因爲i++返回的是右值鴨。

        假設p是int型的指針。則*p++的意義是:先保存p的副本,然後對p加一,然後對未修改的副本執行解引用操作。這是因爲遞增運算符的優先級高於解引用運算符。

六:成員訪問運算符

        p->i 等於 (*p).i 。

七:位運算符

        對char類型執行位運算會提升爲int類型。

八:sizeof運算符

	char i;
	char *p = &i; 
	char &r = i;
	cout << sizeof(char) << endl;
	cout << sizeof i << endl;
	cout << sizeof p << endl;
	cout << sizeof *p << endl;
	cout << sizeof r << endl;

        這段代碼的輸出如下所示:

1
1
4
1
1

        對於類型,sizeof運算符要用括號,對於表達式不需要括號。且可以看出,指針類型佔用四個字節,很厲害的。

九:類型轉換

    unsigned int ui = 10;
	int i = -11;
	unsigned i_ui = i;
	cout << i_ui << endl;
	cout << ui + i << endl;

         對於上面的代碼,輸出如下:

4294967285
4294967295

         可以得出,當運算對象一個是無符號類型,一個是帶符號類型且無符號類型不小於帶符號類型時候,先將帶符號類型轉換成無符號類型再運算。

        強制類型轉換的表達式爲cast_name<type>(expression);其中type爲要轉換的目標類型,expression爲轉換的表達式,cast_name有四種形式:static_cast, const_cast,reinterpret_cast和dynamic_cast;static_cast是最普通的類型轉換,將一種類型轉換爲另一種類型,例如下面這段代碼輸出0.8

    int a = 4, b = 5;
	double d = static_cast<double>(a) / static_cast<double>(b);
	cout << d << endl;

        const_cast改變運算對象的底層const,如下面的代碼所示,將const char*轉換成char*,const_cast不能像static_cast那樣改變表達式類型。

    char ch = '胖';
	const char *p1 = &ch;
	char *p2 = const_cast<char*>(p1);

       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章