1. 程式人生 > 其它 >模板超程式設計與函式式

模板超程式設計與函式式

為什麼需要模板



模板

對於string型別需要特例化
需要顯式轉換string,不然會把字串常量認作const char*

預設模板引數

整數也可以作為引數,不過浮點數,指標型別,自定義型別不能宣告為模板引數,不過為什麼要把int型別作為模板引數呢,直接作為函式引數不行嗎?因為模板裡的int是編譯期常量

可以有多個模板引數

引數部分特化

模板裡的int和函式引數裡的int有什麼區別呢?

  • 根據傳入的模板int引數,編譯器可以做出相應的優化

  • 模板的定義和實現都必須放到標頭檔案中?如果模板將定義與宣告分離,那麼連結時將會出錯這裡也提現了模板的惰性的特點如果一定要分離模板的宣告與定義,那麼需要在定義模板的檔案增加所用到的模板例項化

    模板的惰性的證明

  • 由於模板編譯的時候需要根據模板引數的變化生成不同的例項化函式,所以會使得編譯變慢

編譯期優化,把bool變數放到模板引數中


用C++17的if constexpr進一步保證是編譯期確定的分支,也就是保證if的括號裡是編譯期常量

例項化模板的引數也必須得是編譯器常量

可以在例項化模板的引數放入編譯期常函式

模板函式列印vector還可以過載運算子實現列印

自動型別推導auto

auto的侷限性

auto可以用於函式返回值,如果函式宣告和實現分離了,那麼就不能夠在宣告中使用auto
引用本質上是一個指標常量指標常量本質上是常量,也就是指標的指向不能變,int * const p //指標常量

;而常量指標是指指向常量的指標,指標的指向可以變,但是隻能指向常量,const int *p = &a; //常量指標

常引用就是指向常量的指標常量

懶漢單例模式是這個第一次呼叫函式才會初始化這個static變數

純右值,右值型別int &&

int &&可以自動轉化為int const&,但是不能夠轉為int &

decltype 用來返回變數的型別

decltype((a)),新增括號可以得到int&?陣列取值返回的是引用是因為,比如p[0]得到的是一個左值?

萬能推導(decltype(auto))?

using與typedef意思一致,但是用法更明瞭

decltype用於得到模板函式中的型別值

函數語言程式設計

函式可以當作模板的引數

lambda表示式,可以作為引數

引用捕獲閉包外的變數

這裡傳遞函式的引用,由於捕獲了fac 和 counter兩個變數,那麼傳遞時就是傳遞兩個變數的指標,對於64位os,那麼這個函式twice作為引數傳遞就是16位元組

lambda表示式也可以作為返回值

這裡的lambda表示式捕獲一個棧中的資料,那麼lambda表示式中捕獲的fac的指標(引用)指向的記憶體就被釋放了,
解決方法是用值捕獲,這個時候這個函式的大小是4位元組,猜測是由於值捕獲把數值傳遞進來了

由於模板在這種情況下不能夠去分離宣告與定義,因為lambda表示式型別是匿名的,所以可以使用std::function

std::function開銷較大,無捕獲的lambda表示式可以退化為函式指標

lambda也可以模板化

使用auto表示函式模板

type traits

lmabda表示式的立即求值

lambda實現遞迴

tuple

CTAD(compile-time argument deduction )

C++17結構化繫結
解包為常引用
結構化繫結解包任何自定義類

std::optional

可以用*號去獲取optional容器裡的內容,不過它不會拋異常與檢測是否為空
std::variant可以看作更加安全的union