一、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的数据类型是person
ve.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(不可用)函数。