New Features in C++11 学习

来源:互联网 发布:智能锁屏软件 编辑:程序博客网 时间:2024/06/02 18:06

一、for循环:

1.举例:

vector<int> ve = {0,1,2,3,4,5,6,7,8,9,};for( auto &r : ve)r *= 2;

2.相当于:

for(auto beg = ve.begin(),end = ve.end();beg != end;++beg){auto &r = (*beg);r *= 2;}


二、Lambda表达式:

1.结构:

[]()->{};

2.解释:

[]:一层一层往外捕获值。

[=]:按值进行捕获。

[&]:按引用进行捕获。

():参数

{}:函数体

mutable:表示可以在函数体中修改捕获的值。

3.举例:

void biggies(vector<string> &words,vector<string>::size_type sz,ostream &os = cout,char c = '' ){for_each(words.begin(),words.end(),[&,c](const string &s){os<<s<<c;});for_each(words.begin(),words.end(),[=,&c](const string &s){os<<s<<c;});}
multable的作用:

//如果不加mutable,则不可以修改捕获来的v1,以下代码编译不过//size_t v1 = 42;//auto f = [v1]() {return ++v1;};//加mutable后,编译就可以通过了size_t v1 = 42;{ size_t v1 = 42; auto f = [v1]() mutable {return ++v1;};}

->的作用:

明确指明要返回的类型,如果不写,则编译器会推断返回的类型,但是出现if....else....语句的时候要小心,为了避免错误,最好写明返回类型。

Lambda表达式就是为了简化函数对象所用的,目前我所理解的,他有两个作用。

第一、简化函数对象,如果某个函数中需要用到一个函数对象,而这个函数对象在其他地方就不再需要使用了,此时用Lambda表达式可以简化代码,而不用再去定义一个函数。

第二、传参。例如在find_if函数中,第三个参数的函数对象只能有一个参数,此时如果想要对第三个函数对象传第二个参数的时候。就不能办到了(先撇去bind函数不说)


但是话又说回来了,如果一个函数对象在许多地方都使用到了,如果再写Lambda表达式则会让这个Lambda表达式在许多地方都使用,使得难易管理和复用性太差。

此时我们可以选择用函数对象,增加代码的复用性。

但是问题又来了,如果某个地方需要用到的这个函数对象只能传递限定的参数呢(比如find_if),函数对象如何满足?

此时可以采用bind函数。

void check_size(const string& s,string::size_type sz){return s.size >= sz;}
auto wc = find_if( words.begin,words.end(),bind(check_size,_1,sz));

其中,_n相当于Lambda的()中的参数,sz相当于[]中的值。

注意,bind的参数中,第一个为函数对象的名称,后面的参数为函数对象的参数,并且参数顺序要与函数对象中的参数顺序一致!

如果想捕获一个引用的变量,例如以下例子:

ostream &print(ostream &os,const string &s,char c){return os<<s<<c;}for_each(words.begin(),words.end(),bind(print,os,_1,' ');

for_each中的bind这样写对吗?

其实是错误的。因为bind是传递的一个os的拷贝,而流对象是不能拷贝的。

此时我们应该用ref或cref函数进行包装。

代码如下:

for_each(words.begin(),words.end(),bind(print,ref(os),_1,' ');


三、emplace_back、emplace、emplace_front

1.先介绍emplace,他是构造一个对象的,这三个函数都是给容器用的。

2.举例:

看代码:

vector<Person> ve;   //Person类是一个我自己写的类,包括姓名和性别ve.push_back("huang","male");    //这样是错误的,ve的数据类型是personve.emplace_back("huang","male");    //这样是可以的,因为emplace_back会先构造一个对象,然后再插入ve中

四、将一个函数申明为delete

1.解释:将一个函数申明为delete,表示该函数不可被用。

2.申明形式:void Function() = delete;

3.规则:

(1)如果构造函数或者是析构函数申明为delete,则不可以创建对象。

(2)如果拷贝构造函数被申明为delete,则对象之间不可以进行拷贝。

例如:iostream则不想让多个对象对同一个流进行操作,则此时可以将他的拷贝构造函数申明为delete,这样的话就不会发生拷贝了。

(3)拷贝构造函数有可能被编译器推测为delete的情况有:

1.该类中有一个成员变量,该成员变量的构造函数被申明为delete。

2.该类中有一个成员变量,该成员变量的析构函数被申明为delete。

3.该类中有一个成员变量,该成员变量为一个为被初始化的引用。

写到这里发现上面写的规则有点多余,其实本质上来说,只要是在类中的成员变量有不能被赋值,分配,销毁,则可能造成相应的

函数例如:构造函数、拷贝构造函数、operate = 、析构函数为delete(不可用)函数。






原创粉丝点击