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循环内部做的事情:

 

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