Chinaunix首页 | 论坛 | 博客
  • 博客访问: 470032
  • 博文数量: 143
  • 博客积分: 6159
  • 博客等级: 准将
  • 技术积分: 1667
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-25 23:08
文章分类

全部博文(143)

文章存档

2013年(1)

2012年(11)

2011年(55)

2010年(76)

分类:

2010-11-20 08:55:37

Lambda functions and expressions

In standard C++, particularly when used with C++ standard library algorithm functions such as std::sort and std::find, users will often wish to define predicate functions near the place where they make the algorithm function call. The language has only one mechanism for this: the ability to define a class inside of a function. This is often cumbersome and verbose, and it interrupts the flow of the code. Additionally, standard C++'s rules for classes defined in functions do not permit them to be used in templates, so using them is simply not possible.

The obvious solution would be to allow for the definition of lambda expressions and lambda functions. C++0x will allow for the definition of lambda functions.

A lambda function is defined as follows:

[](int x, int y) { return x + y; }

The return type of this unnamed function is decltype(x+y). The return type can only be omitted if the lambda function is of the form return expression. In that case the lambda function is limited to one statement.

The return type can be explicitly specified as follows, for a more complicated example:

Lambda functions and expressions

In standard C++, particularly when used with C++ standard library algorithm functions such as std::sort and std::find, users will often wish to define predicate functions near the place where they make the algorithm function call. The language has only one mechanism for this: the ability to define a class inside of a function. This is often cumbersome and verbose, and it interrupts the flow of the code. Additionally, standard C++'s rules for classes defined in functions do not permit them to be used in templates, so using them is simply not possible.

The obvious solution would be to allow for the definition of lambda expressions and lambda functions. C++0x will allow for the definition of lambda functions.

A lambda function is defined as follows:

[](int x, int y) { return x + y; }

The return type of this unnamed function is decltype(x+y). The return type can only be omitted if the lambda function is of the form return expression. In that case the lambda function is limited to one statement.

The return type can be explicitly specified as follows, for a more complicated example:

[](int x, int y) -> int { int z = x + y; return z + x; }

In this example, a temporary variable, z, is created to store an intermediate. As with normal functions, the value of this intermediate is not held between invocations.

A lambda function can refer to identifiers declared outside the lambda function. The set of these variables is commonly called a . Closures are defined between square brackets [ and ] in the declaration of lambda expression. The mechanism allows to capture these variables by-value or by-reference. Following table demonstrates this:

[]  //no variables defined. Using one will result in error
[x, &y] //x is captured by value(default), 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

The following two examples demonstrates usage of lambda expression:

std::vector<int> some_list;
int total = 0;
std::for_each(some_list.begin(), some_list.end(), [&total](int x) {
total += x;
});

This would display the total of all elements in the list. The variable total is 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;
int total = 0;
int value = 5;
std::for_each(some_list.begin(), some_list.end(), [&, value](int x) {
total += x * value * this->some_func();
});

This will cause total to be stored as a reference, but value will be stored as a copy. this is implicitly made available in this case (due to & specifier). As this is not an object it is always stored by value. Note that it is required to explicitly refer to this when accessing its members.

If a lambda function is defined by a member function of a class, it is assumed to be a friend of that class. Such lambda functions can use a reference to an object of the class type and access its internal members

The specific internal implementation can vary, but the expectation is that the lambda function 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 for , 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 is .

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 it must create a std::function to capture the lambda value. The use of the auto keyword can locally store the lambda function:

auto my_lambda_func = [&](int x) { /*...*/};

[](int x, int y) -> int { int z = x + y; return z + x; }

In this example, a temporary variable, z, is created to store an intermediate. As with normal functions, the value of this intermediate is not held between invocations.

A lambda function can refer to identifiers declared outside the lambda function. The set of these variables is commonly called a . Closures are defined between square brackets [ and ] in the declaration of lambda expression. The mechanism allows to capture these variables by-value or by-reference. Following table demonstrates this:

[]  //no variables defined. Using one will result in error
[x, &y] //x is captured by value(default), 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

The following two examples demonstrates usage of lambda expression:

std::vector<int> some_list;
int total = 0;
std::for_each(some_list.begin(), some_list.end(), [&total](int x) {
total += x;
});

This would display the total of all elements in the list. The variable total is 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;
int total = 0;
int value = 5;
std::for_each(some_list.begin(), some_list.end(), [&, value](int x) {
total += x * value * this->some_func();
});

This will cause total to be stored as a reference, but value will be stored as a copy. this is implicitly made available in this case (due to & specifier). As this is not an object it is always stored by value. Note that it is required to explicitly refer to this when accessing its members.

If a lambda function is defined by a member function of a class, it is assumed to be a friend of that class. Such lambda functions can use a reference to an object of the class type and access its internal members

The specific internal implementation can vary, but the expectation is that the lambda function 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 for , 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 is .

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 it must create a std::function to capture the lambda value. The use of the auto keyword can locally store the lambda function:

auto my_lambda_func = [&](int x) { /*...*/};

阅读(522) | 评论(0) | 转发(0) |
0

上一篇:老手

下一篇:帮我买个单 [转载]

给主人留下些什么吧!~~