C++11新特性(一)

目錄

variadic-templates可變模版參數

Space in Template Expressions

nullptr and std::nullptr_t

auto

Uniform Initialization (一致性初始化)

Initializer Lists

array

explicit for ctors taking more than one argument

ranged-based for statement --for循環


variadic-templates可變模版參數

語法:typename…,這三個點已經成爲了語言的一部分。

example:

void print()
{
}

template<typename T, typename... Types>
void print(const T& firstArg, const Type&... args)
{
    cout<<firstArg<<endl;
    print(args...);
}

print(7.5, "hello", bitset<16>(377), 42);

hashtable:根據函數輸入參數不同調用1/2/3/4不同方法,具體如下圖所示:

tuple

tuple<int, float,string>:允許你放任意東西,這個是你自己指定,變成一個對象。如下圖所示:

Space in Template Expressions

模版表達式的空格:模版參數本身也是一個模版,有兩個空格。

vector<list<int> > 在每個版本都適用
vector<list<int>>  c++11後可以

nullptr and std::nullptr_t

// C++11之後指針可以用 nullptr代替 0 or NULL
void f(int);
void f(void*);
f(0); // call f(int)
f(NULL); // call f(int) if NULL is 0 ambiguous
f(nullptr); // call f(void*)

auto

概念:不用管一個對象的類型,編譯器會自己去推理其類型

// #1 c++11 you can declare a var or an object without specifiying type by using auto
auto i = 42;
double f();
auto d = f();
// #2 auto用於2種情況 第一種是type太長 另一種是複雜的表達式 lambda 
vector<int> v;
// vector<int>::iterator pos;
// pos = v.begin();
auto pos = v.begin();
auto l = [](int x) -> bool{}//沒有名稱的函數

example:

list<string> c;
...
list<string>::iterator ite;
ite = find(c.begin(), c.end(), target);
//爲了方便,可以用auto
list<string> c;
...
auto ite = find(c.begin(), c.end(), target);//正確寫法

auto ite;									//錯誤寫法
ite = find(c.begin(), c.end(), target);
//如果每次聲明的時候都賦值時,所有的變量都用auto是可以的,但不推薦初學者這樣使用。

Uniform Initialization (一致性初始化)

原理: 編譯器看到大括號 {t1,t2,tn}變做出一個 Initializer_list 他關聯到一個array<T,n> 調用ctor的時候 array內的元素被編譯器被逐一賦值給ctor。但如果參數參數是個Initializer_list 那就將參數打包直接發給函數。

// 如何初始化一個對象或變量,c++11 之前 新手很容易困惑 初始化可能發生在() {} =操作符
// c++11 後統一一個方法 用{}
int a[] = {1,2,3,4};
vector<int> v{2,3,4,5,6};
vector<string> city {
  "New York", "London", "Beijing"
};
comlex<int> c{4.0, 3.0}; // 等價於 c(4.0, 3.0);

// c++ 11 之前
Rect r1 = {3,7,&area};
Rect r1(3,7,&area);

Initializer Lists

爲了完成一致性設初值,大括號背後是做出一個 Initializer_list,個數可變的元素。

1、大括號可以用來設初值。

int i; // i沒有定義初值
int j{}; // j定義初值爲0
int* p; // 指針p沒有初值
int *q{}; // 指針q的初值是nullptr

2、大括號裏的元素類型必須一致

從一致性設初值的方式,瞭解到了{}的作用,下面瞭解以下 Initializer_list的原理。比如下圖例子:

print(定義的容器必須是int類型)。定一個class P類,定義構造函數,測試用例:

#include <iostream>
// #include <initializer_list>
using namespace std;

// 支持函數接受任意個數的參數
// vector<int> v{1,2,3,4,5,6};
// 的實現原理就是將{1,2,3,4,5}包裝成initializer_list 調用參數是initializer_list的ctor
void print(initializer_list<int> vals) {
    for (auto p = vals.begin(); p!=vals.end(); ++p) {
        cout << *p << ' ';
    }
    cout << endl;
}

class P{
public:
    P(int a, int b){
        cout << "P(int a,int b)=" <<a << ' ' << b << endl;
    };
    P(initializer_list<int> initlist) {
        cout << "P(initializer_list<int>)=";
        for(auto i : initlist) {
            cout << i << ' ';
        }
        cout << endl;
    }
};

int main() {
    print({1,2,3,4,5,6,7});

    P p(77,5);
    P q{77,5};
    P r{77,5,23};
    // 調用構造函數
    P s = {77, 5};
}

max/min只能接受兩個參數來對比。

 

array

換個形式的數組。具體的可以看看我寫的STL源碼剖析:https://blog.csdn.net/qq_27262727/article/details/105248954

explicit for ctors taking more than one argument

概念:explicit用來針對構造函數接受一個以上實參。

explicit(明白的,明確的)接收單一實參example

下圖左邊是允許的,下圖右邊加入explicit之後,不允許要編譯器做轉換,必須輸入跟定義的一致才行,否則會報錯。

一個以上輸入實參example:

//!表示加入explicit,報錯的

ranged-based for statement --for循環

for的新形式:使用:來遍歷動作。

//例子1
for(decl : coll) {
  statement
}
// 等價於下面
for(auto pos = coll.begin(), end=coll.end(); pos!=end; ++pos) {
  decl = *pos
    statment
}
//例子2
for(int i : {1,2,3,4,5,1,3}) {
  std::cout << i << ' ';
}
for(auto e : v) {
  std::cout << e << " ";
}
for(auto& e: v) {
  e *= 3;//加入引用,拿出來的東西e會根據操作改變原來元素內容,影響原來的元素,而且引用的話速度會變得很快。
  std::cout << e << " ";
}

for循環內部做的事情:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章