现代C++的一般编程规范
一般情况下不要使用std::endl,尤其是在循环中,因为可能一开始你只是想要打印一个换行符,但是"endl"做的更多,其还会刷新缓冲区,这会额外花费很多时间,相反,只需要使用“\n",就可以做的更好,例如下面这个程序例子。
#include <iostream>void print_Number(int start,int end)
{for(auto i=start;i!=end;i++){std::cout<<i<<"\n";}
}int main()
{print_Number(10,15);
}
当基于范围的for循环能更好的表达意图的时候,却使用索引的for循环
#include <iostream>
#include <vector>void know_your_algorithms()
{const std::vector<int> data={-1,-3,-5,8,15,-1};std::size_t first_pos_idx;for(std::size_t i=0;i<data.size();i++){if(data[i]>0){first_pos_idx=i;break;}}std::cout<<data[first_pos_idx]<<"\n";
}
int main()
{know_your_algorithms();
}
但是在这里我们可以寻找是否已经有算法可以满足我们需要做到的事情,例如下面的例子
#include <iostream>
#include <vector>
#include <algorithm>void know_your_algorithms()
{const std::vector<int> data={-1,-3,-5,8,15,-1};const auto is_positive=[] (const auto &x){return x>0;};auto first_pos_it=std::find_if(data.begin(),data.end(),is_positive);if(first_pos_it!=data.end()){std::cout<<*first_pos_it<<"\n";}
}
int main()
{know_your_algorithms();
}
其中这里的
const auto is_positive=[](const auto &x) {return x>0;};
是C++语言中的lambda表达式,其解释为:
const auto is_positive = [](const auto& x) { return x > 0; };
// ▲ ▲ ▲ ▲ ▲ ▲
// | | | | | |
// 常量 自动类型 Lambda 参数类型 参数 函数体
// | 推导 起始符 推导 引用
[](const auto& x) { return x > 0; }
Lambda表达式简介
[捕获变量] (参数列表) 可选限定符->返回类型{//函数代码
}
#include <iostream>int main()
{int x=7;float y=3.0;auto p=[x,y] (int a,int b)->float{return x*y+a*b;};std::cout<<p(10,20)<<"\n";
}
下面我们直接将lambda表达式作为实际参数传入
#include <iostream>
#include <vector>
#include <algorithm>int main()
{std::vector<float> numbers{1.1,2.0,3.5,-1.4,29.2,12.1,33,6,0};sort(numbers.begin(),numbers.end(),[](float a,float b){return a<b;});for(auto v:numbers) std::cout<<v<<" ";
}
lambda表达式实际上是函数对象的一种快捷定义方式,如果我们用结构体来表示,其为:
#include <iostream>
#include <vector>
#include <algorithm>int main()
{int x=7;float y=3.0;struct{int x;float y;float operator()(int a,int b)const{return x*y+a*b;}}p{x,y};std::cout<<p(10,20);
}
在这里,我们虽然改变了y的值,但是这两个函数的输出是一模一样的
#include <iostream>
#include <vector>
#include <algorithm>int main()
{int x=7;double y=2.3;auto p=[x,y](int a,int b)->float{return x*y+a*b;};std::cout<<p(10,20)<<"\n";y+=1.5;std::cout<<p(10,20)<<"\n";}
原因就是因为lambda函数对象中的对应成员变量只是在初始化时复制了y的值,所以再次使用同样的参数调用函数对象时,结果不会发生变化,但是如果我们在引用的前面加上引用运算符&,则表示其为按引用捕获
#include <iostream>
#include <vector>
#include <algorithm>int main()
{int x=7;double y=2.3;auto p=[&x,&y](int a,int b)->float{return x*y+a*b;};std::cout<<p(10,20)<<"\n";y+=1.5;std::cout<<p(10,20)<<"\n";}
因此其输出的结果为下面
另外,lambda所对应的函数调用运算符默认是const函数,也就是说,函数内部不能修改按值捕获的成员变量,但是可以通过加上mutable修饰符,这样捕获的成员函数都是可以修改的了。
默认捕获方式
//默认按值捕获
[=]
//默认按引用捕获
[&]
#include <iostream>int main()
{int x=7;float y=3.0;float z=-1;auto p=[&](int a,int b)->float{return x*y*z+a*b;};y+=2;std::cout<<p(10,20)<<"\n";
}
这个就是按引用捕获,因此其y发生变化的时候,下面的输出会有变化。
#include <iostream>int main()
{int x=7;float y=3.0;float z=-1;auto p=[=,&y](int a,int b)->float{return x*y*z+a*b;};y+=2;std::cout<<p(10,20)<<"\n";
}