3.1 繼承構造函數
通過using關鍵字可以繼承父類的構造函數。也可以通過顯式定義構造函數來阻止繼承。
3.2 委派構造函數,減少構造函數的書寫
class Info { public: Info() { InitReset(); } Info(int i) : Info() { type = i; } //通過調用無參構造函數,可以減少構造函數內容的重寫 Info(char e) : Info() { name = e; } //委派構造函數和初始化列表不能同時存在,使用委派構造函數后,初始化代碼需要放在函數體中 private: int type { 1 }; //初始化成員變量 char name { 'a' }; void InitReset() {} };
3.3.2 移動語意學
通過移動構造函數可以減少臨時對象中的數據拷貝。
3.3.3 左值、右值和右值引用
有名字的可以取地址的是左值(&a),沒有名字,不能取地址的是右值( &(b+c)是錯誤操作 ),所以a是左值,(b+c)是右值
T && a = ReturnRvalue(); //獲得一個右值引用,只有在a的生命周期中,函數返回的右值持續存活
右值引用不能綁定左值,如 int c; int && d = c; //錯誤
可以通過<type_traits>中的模板類來判斷值的類型,如 is_rvalue_reference<string &&>::value;
3.3.4 std::move 將一個左值強制轉化為右值引用,從而可以通過右值引用使用該值
如果聲明了移動構造函數、移動賦值函數、拷貝賦值函數和析構函數中的一個或多個,編譯器不會再生成默認的拷貝構造函數。所以拷貝構造/賦值和移動構造/賦值函數必須同時提供或者都不提供。
3.5 列表初始化
等號加上賦值表達式,如 int a = 3 + 4;
等號加上花括號,如 int a = {3+4};
圓括號式的表達式 ,如 int a (3+4); 可以用於堆內存的new操作,如 int *i = new int(1);
花括號式的表達式,如int a {3+4}; double *d = new double{2.3f};
使用列表初始化,在出現類型收窄時會編譯失敗,如 char c = {1024}; //無法通過編譯
3.8 字面量操作符 ret operator “” _x(arguments) {} 可以定義字面量操作符
struct Watt { unsigned int v; }; Watt operator "" _w(unsigned long long v) { return { (unsigned int)v }; }
如果字面量為整型數,那么字面量操作符函數只可以接受unsinged long long或const char*為參數
如果字面量為浮點型數,函數只可接受long double或const char*為參數
如果字面量為字符串,函數只接受const char*, size_t為參數
如果字面量為字符,函數只可以接受一個char為參數
4.2 auto 自動類型推導
使用auto聲明的變量必須被初始化,從而使編譯器能夠從初始化表達式中推導出其類型
auto可以用於new關鍵字,auto z = new auto(1);
auto不能用作形參的類型,即使提供了默認參數,如 void fun(auto x = 1) {} //編譯失敗
auto也不能用於結構體的非靜態成員變量,即使成員擁有初始值,如 struct str { auto var = 10; } //編譯失敗
不能聲明auto數組
在實例化模板的時候不能使用auto作為模板參數,如 vecotr<auto> v = {1}; //編譯失敗
4.3 decltype可以用於獲取對象類型,獲取的類型可以用於定義對象,如 vector<int> vec; typedef decltype(vec.beging()) vectype;
decltype只接受表達式作為參數(如,decltype( Func(x)),而不接受 decltype( Func ) ),和auto一樣在編譯時確定類型
4.4 追蹤返回類型,使用auto和decltype可以追蹤返回類型
template<typename T1, typename T2> auto Sum(T1 & t1, T2 & t2) -> decltype(t1 + t2) { return t1 + t2; }
auto (*fp)() -> int; 等價於 int (*fp)();
5.1 強類型枚舉
enum class Type: char { General, Light, Medium, Heavy };
6.1.2 常量表達式函數 constexpr
函數必須有返回值
函數體只有單一的return返回語句,函數體只有一條語句,且這條語句是return。可以有static_assert
在使用前必須已有定義
return 返回語句表達式中不能使用非常量表達式的函數、全局數據,且必須是一個常量表達式
常量表達式的構造函數約束:函數體必須為空;初始化列表只能由常量表達式來賦值。
6.1.3 常量表達式值
const int i = 1; 與 constexpr int j = 1; 大部分情況下相同,區別是如果 i 在全局名字空間中,編譯器一定會為 i 產生數據,而對於 j ,如果不是有代碼顯示地使用了它的地址,編譯器可以選擇不為它產生數據,而僅將其當做編譯器的值。
6.2.2 變長模板
template <typename… Elements> class tuple; // Elements為模板參數包
6.3.2 原子操作 atomic
atomic_llong total {0}; //原子數據類型,多線程訪問時不需要加鎖
std::atomic<T> t; //atomic類模板,可以任意定義出需要的原子類型
原子類型只能從其模板參數類型中進行構造,不允許原子類型進行拷貝構造、移動構造以及使用operator=等。
7.1.2 nullptr
nullptr不能轉換為非指針類型,即使使用 reinterpret_cast<nullptr_t>()的方式也不可以
nullptr不適用於算術運算表達式,也不能進行取地址操作
7.2.2 =default 顯式的聲明函數為缺省函數,=delete 顯式的聲明函數為刪除函數(不可使用和重載)
顯示刪除也可以避免編譯器做一些不必要的隱式數據類型轉換,此時不要和explicit共同使用,如 void Func(char c) = delete; 會導致 Func(‘c’);無法通過編譯
7.3.2 lambda函數
[capture] (parameters) mutable ->return-types {statement}
lambda和仿函數類似,實際上仿函數是編譯器實現lambda的一種方式
對於按值方式傳遞捕捉列表,傳遞的值在lambda函數定義的時候就決定了,而按引用方式傳遞的值則等於lamdba函數調用時的值。
lambda的捕捉列表僅能捕捉父作用域的自動變量,而對超出這個范圍的變量是不能被捕捉的。
8.1.1 alignas 可以設定結構體的對齊方式,alignof獲取結構體的對齊大小
struct alignas(32) AlignedColorVector { double r; double g; double b; double a; };
8.2.2 通用屬性,使用左右雙中括號包含
[[ attribute-list ]]
[[ attr1 ]] void fun [[ attr2 ]] ();
[[ attr1 ]] int array [[ attr2 ]] [10];
C++11中的預定義通用屬性包括 [[ noreturn ]] 標識不會返回的函數,[[ carries_dependency ]] 標識不會將控制流返回給原調用函數的函數,如
[[ noreturn ]] void ThrowAway() {
throw "exception”;
}
8.3.2 UTF-8 采用的變長存儲方式,無法通過數字式訪問讀取數據,更多的使用序列化時節省存儲空間。定長的UTF-16或UTF-32更適合在內存環境中操作。
其他:
在C++11中std的bind1st和bind2st被bind模板所代替