1. 程式人生 > >C++的那些事 1

C++的那些事 1


最近在看c++的一些庫檔案,裡面的一些比較陌生但看起來挺有用的一些東西,在此記下,以免日後看到再翻找資料。

template <size_t _Nb>

這是在看bitset的時候看到的,之前用bitset的時候也沒太留意,這是才發現bitset的類模板引數不是一個型別,而是一個數,這才發現原來類模板引數也可以是一個數。

C++ Primer的654頁提到了Nontype Template Parameters就是指這個,來看一下他給的例子。

template <unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
    return strcmp(p1, p2);
}

當我們呼叫

compare("hi", "mom");

相當於是呼叫了

int compare(const char (&p1)[3], const char (&p2)[4])

也就是說Nontype Template Parameters跟我們平常所用的模板其實是類似的,只不過平常所用的模板引數是資料型別,而這個是數,bitset就是用這個來宣告bitset的位數。
這時,如果類中的一個常量成員與模板引數有關,那麼這個常量成員要設為靜態常量,因為對於同一個例項模板,這個成員是靜態的(不隨新建物件而改變)。

array

我們經常用new[]來新建一個數組,但這樣很容易出錯,如果不小心把頭指標弄丟了,那麼整個陣列就沒了,而且新建出來的記憶體也會浪費掉,所以C++11新添加了一個array的資料新型,新建以後就當陣列用就是了,而且與陣列一樣,它的記憶體儲存是連續的。

Rvalue Reference(右值引用)

bitset::insert(const_iterator position, value_type&& val)

上面程式碼中的value_type&& val就是右值引用的一個例子,在C++ Primer的532頁有關於Rvalue Reference的介紹,這個的主要使用是在物件要被釋放之前將物件的資源(內容)移出來,而不是進行復制操作,就像原文所說的:
Rvalue reference refer to objects that are about to be destroyed. Hence, we can "steal" state from an object bound to an rvalue reference.


在平常的使用中可能沒有感受到右值引用帶來的好處,特別是對"steal"如何理解,我覺得知乎上Tinro的回答中對"steal"的解釋挺詳細的,通過右值引用這個概念可以進行很多優化。

Variadic Template

在看到這個的時候,我特別開心,因為我知道Matlab是有這個功能的,以前以為C++沒有這個功能,覺得怪可惜的,現在發現可以這樣用,而且與tuple配合使用可以產生許多好用的功能,舉個例子(C++ Primer第700頁)

template <typename T, typename... Args>
void foo(const T &t, const Args&... rest);

這就是一個可變引數模板,其中Args是一個模板引數包,rest是一個函式引數包,因此foo函式的引數只要大於一個就行,下面是一些呼叫的例子

int i=0; double d=3.14; string s="variadic";
foo(i, s, 42, d);    //包中有三個引數
foo(s, 42, "hi");   //包中有兩個引數
foo(d, s);            //包中有一個引數
foo("hi");            //包中沒有引數

如果對rest進行取地址的處理,那麼得到的會是rest裡面所有變數都取地址,用cout輸出時,只需cout << rest即可按順序輸出引數。
但如果要對引數進行運算,就要用到tuple這一資料型別,tuple的每個變數的型別都可以不一樣,支援取某個變數的型別,取值等操作,這樣只要把用(Args, rest)新建一個tuple,就可以對裡面的值進行修改。下面是tuple的例子

tuple< string, vector<double>, int, list<int> > someVal("constants", {3.14, 2.718}, 42, {0,1, 2, 3, 4, 5});
typedef decltype(someVal) trans;    //trans: <string, vector<double>, int, list<int> >
tuple_element<2, trans>::type cnt=get<2>(someVal);   
 //tuple_element<2, trans>::type :取trans中的第2個型別,get<1>(someVal) :取someVal中的第2個數。
//所以cnt的型別為int, 數值為42