Anonymous function in C++
2016-04-19 16:11
302 查看
C++ (since C++11)
C++11 provides support for anonymous functions, calledlambda expressions. A lambda expression has the form:[capture](parameters) -> return_type { function_body }
An example lambda function is defined as follows:
[](int x, int y) -> int { return x + y; }
C++11 also supports
closures. Closures are defined between square brackets
[and
]in the declaration of lambda expression. The mechanism allows these variables to be captured by value or by reference. The following table demonstrates this:
[] //no variables defined. Attempting to use any external variables in the lambda is an error. [x, &y] //x is captured by value, y is captured by reference [&] //any external variable is implicitly captured by reference if used [=] //any external variable is implicitly captured by value if used [&, x] //x is explicitly captured by value. Other variables will be captured by reference [=, &z] //z is explicitly captured by reference. Other variables will be captured by value
Variables captured by value are constant by default. Adding
mutableafter the parameter list makes them non-constant.
The following two examples demonstrate usage of a lambda expression:
std::vector<int> some_list{ 1, 2, 3, 4, 5 }; int total = 0; std::for_each(begin(some_list), end(some_list), [&total](int x) { total += x; });
This computes the total of all elements in the list. The variable
totalis stored as a part of the lambda function's closure. Since it is a reference to the stack variable
total, it can change its value.
std::vector<int> some_list{ 1, 2, 3, 4, 5 }; int total = 0; int value = 5; std::for_each(begin(some_list), end(some_list), [&, value, this](int x) { total += x * value * this->some_func(); });
This will cause
totalto be stored as a reference, but
valuewill be stored as a copy.
The capture of
thisis special. It can only be captured by value, not by reference.
thiscan only be captured if the closest enclosing function is a non-static member function. The lambda will have the same access as the member that
created it, in terms of protected/private members.
If
thisis captured, either explicitly or implicitly, then the scope of the enclosed class members is also tested. Accessing members of
thisdoes not require explicit use of
this->syntax.
The specific internal implementation can vary, but the expectation is that a lambda function that captures everything by reference will store the actual stack pointer of the function it is created in, rather than individual references to stack variables.
However, because most lambda functions are small and local in scope, they are likely candidates forinlining, and thus will not need any additional
storage for references.
If a closure object containing references to local variables is invoked after the innermost block scope of its creation, the behaviour isundefined.
Lambda functions are function objects of an implementation-dependent type; this type's name is only available to the compiler. If the user wishes to take a lambda function as a parameter, the type must be a template type, or they must create a
std::function
or a similar object to capture the lambda value. The use of the
autokeyword can help store the lambda function,
auto my_lambda_func = [&](int x) { /*...*/ }; auto my_onheap_lambda_func = new auto([=](int x) { /*...*/ });
Here is an example of storing anonymous functions in variables, vectors, and arrays; and passing them as named parameters:
#include <functional> #include <vector> #include <iostream> double eval(std::function <double(double)> f, double x = 2.0) { return f(x); } int main() { std::function<double(double)> f0 = [](double x){return 1;}; auto f1 = [](double x){return x;}; decltype(f0) fa[3] = {f0,f1,[](double x){return x*x;}}; std::vector<decltype(f0)> fv = {f0,f1}; fv.push_back ([](double x){return x*x;}); for(int i=0;i<fv.size();i++) std::cout << fv[i](2.0) << std::endl; for(int i=0;i<3;i++) std::cout << fa[i](2.0) << std::endl; for(auto &f : fv) std::cout << f(2.0) << std::endl; for(auto &f : fa) std::cout << f(2.0) << std::endl; std::cout << eval(f0) << std::endl; std::cout << eval(f1) << std::endl; std::cout << eval([](double x){return x*x;}) << std::endl; return 0; }
A lambda expression with an empty capture specification (
[]) can be implicitly converted into a function pointer with the same type as the lambda was declared with. So this is legal:
auto a_lambda_func = [](int x) { /*...*/ }; void (* func_ptr)(int) = a_lambda_func; func_ptr(4); //calls the lambda.
The
Boost library provides its own syntax for lambda functions as well, using the following syntax:[11]
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
相关文章推荐
- Atrenta电话面试(C++研发工程师)
- c++ memset、memcpy函数
- 同花顺面试经验(搜索引擎C++后台研发)
- Effective C++笔记(四):设计与声明
- c++中在顺序容器中访问、插入、删除元素的操作
- 第4周 C语言及程序设计提高例程-5 函数的参数
- 学习C++ effective
- C++11 生成指定范围内的随机数
- C++项目之文件的压缩及解压缩
- STL的学习(C++primer)
- 使用SWIG将C++接口转换成Java接口
- 使用grep 在源码文件查找特定字符串
- showFilesName.cpp
- C++ 继承
- leetcode111题 题解 翻译 C语言版 Python版
- c++各容器使用心得
- C语言里栈和堆的区别整理
- 每个数不会超过100位 怎么用C语言写啊 ,谢谢我是一只菜鸟
- 输入十个字符,存放到数组中,然后顺序打印出来。C语言新手
- leetcode112题 题解 翻译 C语言版 Python版