-
如果你的數(shù)值超過了int表示范圍,選用long long
-
如果你需要使用一個不大的整數(shù),那么明確指定它的類型是signed char或者unsigned char
-
執(zhí)行浮點數(shù)運算選用double
-
當(dāng)一個算術(shù)表達式中既有無符號數(shù)又有int值時,那個int值就會轉(zhuǎn)換成無符號數(shù)。
-
當(dāng)從無符號數(shù)中減去一個值時,不管這個值是不是無符號數(shù),我們都必須確保結(jié)果不能是一個負(fù)值。
-
分行書寫的字符串字面值
std::cout << "a really, really long string literal "
"that spans two lines" << std::endl;
-
如果反斜線\后面跟著的八進制數(shù)字超過3個,只有前3個數(shù)字與\構(gòu)成轉(zhuǎn)義序列。
-
字符和字符串字面值
| 前綴 |
含義 |
類型 |
| u |
Unicode 16字符 |
char16_t |
| U |
Unicode 32字符 |
char32_t |
| L |
寬字符 |
wchar_t |
| u8 |
UTF-8(僅用于字符串字面常量) |
char |
-
整型字面值
| 后綴 |
最小匹配類型 |
| u or U |
unsigned |
| l or L |
long |
| ll or LL |
long long |
-
浮點型字面值
| 后綴 |
類型 |
| f or F |
float |
| l or L |
long double |
-
我們在使用對象這個詞時,并不嚴(yán)格區(qū)分是類還是內(nèi)置類型,也不區(qū)分是否命名或是否只讀。
-
初始化和賦值是兩個完全不同的操作。
-
初始化不是賦值,初始化的含義是創(chuàng)建變量時賦予其一個初始值,而賦值的含義是把對象的當(dāng)前值擦除,而已一個新值來替代。
-
列表初始化:
int unit = 0;
int unit = {0};
int unit{0};
int unit(0);
long double ld = 3.1415926536;
int a{ld}, b = {ld}; // 錯誤:轉(zhuǎn)換未執(zhí)行,因為存在丟失信息的危險
int c(ld), d = ld; // 正確:轉(zhuǎn)換執(zhí)行,且確實丟失了部分值
-
在函數(shù)體內(nèi)部的內(nèi)置類型變量將不被初始化。
-
變量聲明
extern int i; // 聲明i而非定義i
int j; // 聲明并定義j
-
任何包含了顯示初始化的聲明即成為定義。
-
變量能且只能被定義一次,但是可以被多次聲明。
-
用戶自定義的標(biāo)識符中不能連續(xù)出現(xiàn)兩個下劃線,也不能以下劃線緊連大寫字母開頭。此外,定義在函數(shù)體外的標(biāo)識符不能以下劃線開頭。
-
因為全局作用域本身并沒有名字,所以當(dāng)作用域操作符的左側(cè)為空時,向全局作用域發(fā)出請求獲取作用域操作符右側(cè)名字對應(yīng)的變量。
#include<iostream>
using namespace std;
int reused = 1;
int main()
{
int reused = 2; // 局部變量
::reused = 3;
reused = 4;
cout << "reused: " << reused << endl;
cout << "::reused: " << ::reused << endl; // 顯示地訪問全局變量
return 0;
}
-
引用必須被初始化
int iVal = 1024;
int &refVal = iVal; // refVal是iVal的另一個名字
-
無法令引用重新綁定到另外一個對象,因此引用必須初始化。
-
引用并非對象,相反的,它只是為一個已經(jīng)存在的對象所起的另外一個名字。
-
因為引用本身不是一個對象,所以不能定義引用的引用。
-
除兩種例外情況外,引用類型都要和與之綁定的對象嚴(yán)格匹配。而且,引用只能綁定在對象上,而不能與字面值或某個表達式的計算結(jié)果綁定在一起。
-
因為引用不是對象,沒有實際地址,所以不能定義指向引用的指針。
-
現(xiàn)在的C++程序最好使用nullptr,同時盡量避免使用NULL。
-
把int變量直接賦給指針是錯誤的操作。
int zero = 0;
int *pi = zero;
-
賦值永遠改變的是等號左側(cè)的對象。
-
對于兩個類型相同的合法指針,可以用相等操作符(==)或不相等操作符(!=)來比較它們,比較的結(jié)果是布爾類型。如果兩個指針存放的地址值相同,則它們相等;反之它們不相等。
-
void*指針:
- 拿它和別的指針比較、作為函數(shù)的輸入或輸出
- 賦給另外一個void*指針
- 不能直接操作void*指針?biāo)傅膶ο?/li>
-
定義多個變量:
int *p1, *p2;
int* p1; int* p2;
-
指針是對象,所以存在對指針的引用。
-
默認(rèn)情況下,const對象被設(shè)定為僅在文件內(nèi)有效。
-
如果想在多個文件之間共享const對象,必須在變量的定義之前添加extern關(guān)鍵字。
-
常量引用是對const的引用
const int ci = 1024;
const int &r1 = ci; // 正確:引用及其對應(yīng)的對象都是變量
r1 = 42; // 錯誤:r1是對常量的引用
int &r2 = ci; // 錯誤:試圖讓一個非常量引用指向一個常量對象
-
初始化和對const的引用
double dval = 3.14;
const int &ri = dval; // 注意,如果ri非const就非法
/*
* 編譯器把上述代碼變成了如下形式:
* const int tmp = dval; // 由雙精度浮點數(shù)生成一個臨時的整型常量
* const int &ri = tmp; // 讓ri綁定這個臨時量
*/
-
當(dāng)執(zhí)行對象的拷貝操作時,頂層const不受影響,底層const的限制不能忽視??饺牒涂匠龅膶ο蟊仨毦哂邢嗤牡讓觕onst資格,或者兩個對象的數(shù)據(jù)類型必須能夠轉(zhuǎn)換。一般來說,非常量可以轉(zhuǎn)換成常量,反之則不行。
-
常量表達式是指值不會改變并且在編譯過程就能得到計算結(jié)果的表達式。一個對象(或表達式)是不是常量表達式由它的數(shù)據(jù)類型和初始值共同決定。
-
聲明為constexpr的變量一定是一個常量,而且必須用常量表達式初始化。
-
一般來說,如果你認(rèn)定變量是一個常量表達式,那就把它聲明成constexpr類型。
-
聲明constexpr時使用字面值類型。算術(shù)類型、引用和指針都屬于字面值類型。自定義類、IO庫、string類則不屬于字面值類型,也就不能被定義成constexpr。
-
一個constexpr指針的初始值必須是nullptr或者0,或者是存儲與某個固定地址中的對象。函數(shù)體內(nèi)定義的變量一般來說并非存放在固定地址中,因此constexpr指針不能指向這樣的變量。相反的,定義于所有函數(shù)體之外的對象其地址固定不變,能用來初始化constexpr指針。
-
限定符constexpr僅對指針有效,與指針?biāo)傅膶ο鬅o關(guān)。
const int *p = nullptr; // p是一個指向整型常量的指針
constexpr int *q = nullptr; // q是一個指向整數(shù)的常量指針
-
constexpr把它所定義的對象置為了頂層const。
-
與其他常量指針類似,constexpr指針既可以指向常量也可以指向一個非常量。
constexpr int *np = nullptr; // np是一個指向整數(shù)的常量指針,其值為空
int j = 0;
constexpr int i = 42; // i的類型是整型常量
// i和j都必須定義在函數(shù)體之外
constexpr const int *p = &i; // p是常量指針,指向整型常量i
constexpr int *p1 = &j; // p1是常量指針,指向整數(shù)j
-
類型別名:
typedef double wages;
using wages = double;
typedef char *pstring;
using pstring = char*;
const pstring cstr = 0; // cstr是指向char的常量指針(注意,不能理解為const char *cstr = 0;)
const pstring *ps; // ps是一個指針,它的對象是指向char的常量指針
-
auto讓編譯器通過初始值來推算變量的類型。顯然,auto定義的變量必須有初始值。
-
因為一條聲明語句只能有一個基本數(shù)據(jù)類型,所以該語句中所有變量的初始基本數(shù)據(jù)類型都必須一樣。
auto i = 0, *p = &i; // 正確
auto sz = 0, pi = 3.14; // 錯誤
-
使用引用其實是使用引用的對象。特別是當(dāng)引用被用作初始值時,真正參與初始化的其實是引用對象的值。此時編譯器以引用對象的類型作為auto的類型。
-
auto一般會忽略掉頂層const,同時底層const則會保留下來。
int i = 0;
const int ci = i, &cr = ci;
auto b = ci; // b是一個整數(shù)
auto c = cr; // c是一個整數(shù)
auto d = &i; // d是一個整型指針
auto e = &ci; // e是一個指向整數(shù)常量的指針(對常量對象取地址是一種底層const)
-
如果希望推斷出的auto類型是一個頂層const,需要明確指出:const auto f = ci;
-
還可以將引用的類型設(shè)為auto,設(shè)置一個類型為auto的引用時,初始值中的頂層常量屬性仍然保留
auto &g = ci; // g是一個整型常量的引用,綁定到ci
auto &h = 42; // 錯誤:不能為非常量引用綁定字面值
const auto &j = 42; // 正確:可以為常量引用綁定字面值
-
要在一條語句中定義多個變量,切記,符號&和*只從屬于某個聲明符,而非基本數(shù)據(jù)類型的一部分,因此初始值必須是同一種類型:auto &m = ci, *p = &ci;
-
decltype的作用是選擇并返回操作數(shù)的數(shù)據(jù)類型。在此過程中,編譯器分析表達式并得到它的類型,卻不實際計算表達式的值。(如:decltype(f()) sum = x;中sum的類型就是函數(shù)f的返回類型,但不實際調(diào)用函數(shù)f)
-
如果decltype使用的表達式是一個變量,則decltype返回該變量的類型(包括頂層const和引用在內(nèi)),需要指出的是,引用從來都作為其所指對象的同義詞出現(xiàn),只有用在decltype處是一個例外。
-
如果decltype使用的表達式不是一個變量,則decltype返回表達式結(jié)果對應(yīng)的類型。
- 如果該表達式的結(jié)果對象能作為一條賦值語句的左值,decltype返回一個引用類型。
- 如果表達式的內(nèi)容是解引用操作,則decltype將得到引用類型。
- 如果給變量加上了一層或多層括號,編譯器就會把它當(dāng)成是一個表達式。變量是一種可以作為賦值語句左值的特殊表達式,所以這樣的decltype就會得到引用類型。(切記:
decltype((variable))(注意是雙層括號)的結(jié)果永遠是引用,而decltype(variable)結(jié)果只有當(dāng)variable本身就是一個引用時才是引用。)
-
賦值是會產(chǎn)生引用的一類典型表達式,引用的類型就是左值的類型,如果i是int,則表達式i=x的類型是int&。
-
類體右側(cè)的表示結(jié)束的花括號后必須寫一個分號,這是因為類體后面可以緊跟變量名以示對該類型對象的定義,所以分號必不可少(很多新手程序員經(jīng)常忘了在類定義的最后加上分號)。分號表示聲明符(通常為空)的結(jié)束。一般來說,最好不要把對象的定義和類的定義放在一起。
-
類的數(shù)據(jù)成員定義了類的對象的具體內(nèi)容,每個對象有自己的一份數(shù)據(jù)成員拷貝。
-
C++11規(guī)定,可以為數(shù)據(jù)成員提供一個類內(nèi)初始值。對類內(nèi)初始值的限制與之前介紹的類似:或者放在花括號里,或者放在等號右邊,記住不能使用圓括號(因為會和函數(shù)聲明混淆)。
-
預(yù)處理變量無視C++語言中關(guān)于作用域的規(guī)則。