C++11 ,14,17 出來好多年了,但是一直沒有系統的去整理一凡。

趁著這段時間比較空,來一波溫故而知新。

有一些新概念,還有一些竟然自己一直理解錯了或者被人誤導了。

有些東西我覺得是多餘的東西,但是可以用來幫助看

開原始碼

1。C++型別後置(C++11的玩法,在14以後的版本里已經沒必要了)

這種其實就是一種語法糖吧,想不出實際用途在哪。

難道是想用auto來自動推導模板的返回值。

template

auto add(T t, U u) -> decltype(t + u)

{

return t + u;

}

2。完美轉發 std::forward

首先解釋一下什麼是完美轉發,它指的是函式模板可以將自己的引數“完美”地轉發給內部呼叫的其它函式。所謂完美,即不僅能準確地轉發引數的值,還能保證被轉發引數的左、右值屬性不變。

完美轉發這樣嚴苛的引數傳遞機制,很常用嗎?C++98/03 標準中幾乎不會用到,但 C++11 標準為 C++ 引入了右值引用和移動語義,因此很多場景中是否實現完美轉發,直接決定了該引數的傳遞過程使用的是複製語義(呼叫複製建構函式)還是移動語義(呼叫移動建構函式)。

因為引入了移動複製函式,左值,又值等概念,所以這個還是挺常用的,特別是在stl原始碼裡有很多。

#include

using namespace std;

//過載被呼叫函式,檢視完美轉發的效果

void otherdef(int & t) {

cout << “lvalue\n”;

}

void otherdef(const int & t) {

cout << “rvalue\n”;

}

//實現完美轉發的函式模板

template

void function(T&& t) {

otherdef(forward(t));

}

int main()

{

function(5);

int x = 1;

function(x);

return 0;

}

輸出為

rvalue

lvalue

3。返回值最佳化

返回值最佳化

(Return value optimization,縮寫為RVO)是C++的一項編譯最佳化技術,即刪除保持函式返回值的臨時物件。這可能會省略兩次複製建構函式,即使複製建構函式有副作用。典型地,當一個函式返回一個物件例項,一個臨時物件將被建立並透過

複製建構函式

把目標物件複製給這個臨時物件。C++標準允許省略這些複製建構函式,即使這導致程式的不同行為,即使編譯器把兩個物件視作同一個具有副作用。

備註,我以前的認知裡,函式返回值的的時候,會複製一份。例如如下程式碼

應該會呼叫2次建構函式,一次複製建構函式,而實際上則是執行了一次建構函式 + 一次移動建構函式。

class A

{

public:

A();

~A();

A(const A& d);

A(A&& d);//移動建構函式

};

A::A()

{

printf(“construction !!\n”);

}

A::A(A&& d)

{

printf(“construction move !!\n”);

}

A::A(const A& d)

{

printf(“construction copy !!\n”);

}

A::~A()

{

}

A func()

{

A a;

return a;

}

int main() {

A b = func();

}

輸出

construction !!

construction move !!

4。函式模板的預設模板引數

函式模板有預設引數這事倒真沒使用過,做個記錄吧,一些開原始碼裡很常見。

如果能夠從函式實參中推匯出型別的話,那麼預設模板引數就不會被使用,反之,預設模板引數則可能會被使用

比如STL原始碼裡的這部分程式碼

template

struct integral_constant {

static constexpr _Ty value = _Val;

using value_type = _Ty;

using type = integral_constant;

constexpr operator value_type() const noexcept {

return value;

}

_NODISCARD constexpr value_type operator()() const noexcept {

return value;

}

};

template

using

bool_constant

= integral_constant

using true_type = bool_constant

using false_type = bool_constant

5。列表初始化

(1)。 型別是一個普通陣列,如int[5],char[],double[]等

(2)。 型別是一個類,且滿足以下條件:

沒有使用者宣告的建構函式

沒有使用者提供的建構函式(允許顯示預置或棄置的建構函式)

沒有私有或保護的非靜態資料成員

沒有基類

沒有虛擬函式

沒有{}和=直接初始化的非靜態資料成員

沒有預設成員初始化器

struct A {

public:

A(int) {}

private:

A(const A&) {}

};

int main() {

A a(123);

A b = 123; // error

A c = { 123 };

A d{123}; // c++11

int e = {123};

int f{123}; // c++11

return 0;

}

我寫程式碼全蒙的。