分类:
2010-11-20 08:55:37
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:
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) { /*...*/};