4年过去了,还是程序媛小白。导师让看看关于Lambda算子的东西,才第一次知道函数式编程,lambda算子,艰难的进阶之路。记录一下学习历程。总结一下看过的资料。
原作:https://www.cnblogs.com/haippy/archive/2013/05/31/3111560.html
http://blog.csdn.net/u011437229/article/details/78696599
“函数式编程”是一种“编程范式”,主要思想是把运算过程尽量写成一系列嵌套的函数调用。
匿名函数是许多编程语言都支持的概念,有函数体,没有函数名。1958年,lisp首先采用匿名函数,匿名函数最常用的是作为回调函数的值。正因为有这样的需求,c++引入了lambda 函数,你可以在你的源码中内联一个lambda函数,这就使得创建快速的,一次性的函数变得简单了。例如,你可以把lambda函数可在参数中传递给std::sort函数。
#include
#include
void abssort(float* x, unsigned N) {
std::sort(x, x + N,
// Lambda expression begins
[](float a, float b) {
return std::abs(a) < std::abs(b);
});
}
其中(1)是完整的Lambda表达式形式,
(2)const类型的lambda表达式,该类型的表达式不能改捕获(“capture”)列表中的值。
(3)省略了返回值类型的lambda表达式,但该表达式的返回类型可以按照一定规则推断出来:
如果lambda代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。
如果没有 return 语句,则类似 void f(…) 函数。
(4)省略了参数列表,类似于无参函数 f()。
mutable 修饰符说明 lambda 表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获对象的 non-const 方法。
exception 说明 lambda 表达式是否抛出异常(noexcept),以及抛出何种异常,类似于void f() throw(X, Y)。
attribute 用来声明属性。
另外,capture 指定了在可见域范围内 lambda 表达式的代码内可见得外部变量的列表,具体解释如下:
[a,&b] a变量以值的方式呗捕获,b以引用的方式被捕获。
[this] 以值的方式捕获 this 指针。
[&] 以引用的方式捕获所有的外部自动变量。
[=] 以值的方式捕获所有的外部自动变量。
[] 不捕获外部的任何变量。
#include
#include "iostream"
#include
#include
//由浅到深,循序渐进的感受lambda的神奇之处
void lambda_one() {
std::cout << std::endl << "----------没有函数参数的lambda---------" << std::endl;
auto fun = []() {};
auto fun1 = []() { std::cout << "fun1" << std::endl; };
fun1();
std::cout << std::endl << "--------for_each中使用简单的lambda------" << std::endl;
std::vector<int> v(3, 5);
for_each(v.begin(), v.end(), [](int num) { std::cout << num << "\t"; });
std::cout << std::endl << "---------设置lambda的返回值类型--------" << std::endl;
std::cout << [](double a, double b) { return a + b; }(1.4, 2.5) << std::endl;
std::cout << [](double a, double b) -> int { return a + b; }(1.4, 2.5) << std::endl;
std::cout << std::endl << "---------lambda中的传值---------------" << std::endl;
int x = 1;
int y = 100;
[=](double a, double b)mutable -> int {
std::cout << "lambda:" << (x = 100) << "\t" << (y = 10) << std::endl;
return a + b;
}(1.4, 2.5);
std::cout << "main:" << x << "\t" << y << std::endl;
std::cout << std::endl << "---------lambda中的传引用--------------" << std::endl;
[&x, &y](double a, double b) -> int {
std::cout << "lambda:" << (x = 100) << "\t" << (y = 10) << std::endl;
return a + b;
}(1.4, 2.5);
std::cout << "main:" << x << "\t" << y << std::endl;
std::cout << std::endl << "-----------lambda中的传引用和引用传递------" << std::endl;
//等号必须写在前面,或者也可以[x,&y].
//=表示,除了&y,其他所有的外部变量都可以按照值传递进行访问。
//注:不知道是否有人跟我一样,在这儿困惑了很久呢?按照道理来说,[=,&y]一个传值,一个传引用,那么x(以复制方式捕获的)在main输出结果应该是1,而不是100。找了一些资料,是这样解释的:
//虽然按值捕获的变量值均补复制一份存储在lambda表达式变量中,修改他们也并不会真正影响到外部,但我们却仍然无法修改它们。
//那么如果希望去修改按值捕获的外部变量,需要显示指明lambda表达式为mutable。mutable表示非引用的值也可读可写,但不能返回
//需要注意:被mutable修饰的lambda表达式就算没有参数也要写明参数列表。
//原因:lambda表达式可以说是就地定义仿函数闭包的“语法糖”。它的捕获列表捕获住的任何外部变量,最终均会变为闭包类型的成员变量。按照C++标准,lambda表达式的operator()默认是const的,一个const成员函数是无法修改成员变量的值的。而mutable的作用,就在于取消operator()的const。
[=, &y](double a, double b) mutable -> int {
std::cout << "lambda:" << (x = 100) << "\t" << (y = 10) << std::endl;
return a + b;
}(1.4, 2.5);
std::cout << "main:" << x << "\t" << y << std::endl;
}
void lambda_two() {
// sort 排序
using namespace std;
std::cout << std::endl << "-----------sort排序中使用lambda------" << std::endl;
int a[8] = {6, 8, 3, 4, 9, 2, 7, 1};
sort(begin(a), end(a), [](const int &a, const int &b) -> bool { return a < b; });
for_each(begin(a), end(a), [](const int &num) { cout << num << "\t"; });
cout << endl << "-----------------------------------------------" << endl;
}
void lambda_three() {
// (lambda递归) 3个数返回最大的两个数的和
using namespace std;
function<int(int, int, int)> f = [&f](int a, int b, int c) -> int {
if (a <= b && a <= c) {
return b + c;
}
return f(b, c, a);
};
cout << f(4, 1, 6) << endl;
}
void lambda_four() {
//判断数组中的偶数个数,两种写法
std::vector<int> v = {1, 2, 3, 4, 5};
int even_count = 0;
int even_count_x = std::count_if(v.begin(), v.end(), [](int x){return x % 2 == 0;});
std::for_each(v.begin(), v.end(), [&even_count](int val) {
if (!(val & 1)) {
++even_count;
}
});
std::cout << "method1:the number of even is " << even_count << std::endl;
std::cout << "methods:the number of even is " << even_count_x << std::endl;
}
/**
* @anchor xin
* 功能描述:生成一个随机整数列表,并判断其中多少个整数克被3整除,多少个整数被13整除
*/
#include
#include
#include
#include
#include
const unsigned long Size1 = 39L;
const unsigned long Size2 = 100 * Size1;
const unsigned long Size3 = 100 * Size2;
bool f3(int x) { return x % 3 == 0; };
bool f13(int x) { return x % 13 == 0; };
int main() {
using namespace std;
std::vector<int> numbers(Size1);
std::srand(static_cast<unsigned int>(std::time(0)));
std::generate(numbers.begin(), numbers.end(), std::rand);
//using function pointers
cout << "Samples size=" << Size1 << endl;
auto count3 = std::count_if(numbers.begin(), numbers.end(), f3);
cout << "Count of numbers divisible by 3:" << count3 << endl;
auto count13 = std::count_if(numbers.begin(), numbers.end(), f13);
cout << "Count of numbers divisible by 13:" << count13 << endl;
//increase number of numbers
numbers.resize(Size2);
std::generate(numbers.begin(), numbers.end(), std::rand);
cout << "Samples size=" << Size2 << endl;
//using a functor
class f_mod {
private:
int dv;
public:
f_mod(int d = 1) : dv(d) {};
bool operator()(int x) { return x % dv == 0; }
};
count3 = std::count_if(numbers.begin(), numbers.end(), f_mod(3));
cout << "Count of numbers divisible by 3:" << count3 << endl;
count13 = std::count_if(numbers.begin(), numbers.end(), f_mod(13));
cout << "Count of numbers divisible by 13:" << count13 << endl;
//increase number of numbers again
numbers.resize(Size3);
std::generate(numbers.begin(), numbers.end(), std::rand);
cout << "Samples size=" << Size3 << endl;
//using lambda
count3 = std::count_if(numbers.begin(), numbers.end(), [](int x) { return x % 3 == 0; });
cout << "Count of numbers divisible by 3:" << count3 << endl;
count3 = std::count_if(numbers.begin(), numbers.end(), [](int x) { return x % 13 == 0; });
cout << "Count of numbers divisible by 13:" << count13 << endl;
return 0;
}