all aspects of lamda expression

Some tips about the cpp lambda expression.

When you start to use the cpp, one thing that can not be avoided is the lambda expression. The senior programmer may use it a lot and consider it as a flexible way to do things. But the junior programmer may think it is hard to understnad.

Most of the detilas about the lambda expression can be found here, and I jsut list some points that might be neglected.

capture all

& (implicitly capture the used automatic variables by reference)

= (implicitly capture the used automatic variables by copy)

but the good practice is not do capture all, to controle the captured variable in an explicit way. The reason why the capture was problematic is that with [&] you capture everything by reference, including variables on stack. When the thread actually starts executing (if we assume the lambda exprestion is used to start another thread and it is executed asyncronous with the current thread), your are already outside of the calling function and these references don’t point to something valid anymore on the stack.

it is crutial to figure out the life cycle and the scope of every variable, which is temporay variable that in the scope of the function, which is belong to class, which is on the heap. By this way, it is easy to figure out if you need to copy a variable or use reference for it.

essentially, the goal of the capture part is just to set the context for actual task, some variables maybe used in the task and they should be initilized well when writting the lambda expression.

functor vs the lambda expression

it seems the lambda expression are really similar with the functors (function opject, callable object) in cpp, the functors are more general case, but some times, using the lambda expression properly and simplify the soure code.

For example, if we want the customized struct to be a key of the unorderd_map, we may need to provide a function object that contains the hash function of the self defined class/struct.

But for other case, such as the find_if operation, the third parameter might be a lambda expression, which is more simple for the code.

std::find_if(req_list.begin(), req_list.end(),
[src, tag](const key_req &k) { return k.m_tag == tag;});

for this case, we want to find firt value that have the same key, and the key is determined during the program execution, we may need more redoundant code to wrap the simple operation k.m_tag == tag if we use the functor.

Simple lambda function in one line

If there is smaller function in the code, just using this type of lambda function to do the smaller function call. Capture all variables, no input variables, do some simple operations, such as updating some metadata.

[&](){ do sth, return} ();

Some typical use cases

When there are two levels or several levels of for loop, we may try to return the results when we find specific i,j,k that satisfies specific condition. This is how we use it by lambda expression:

[&](){
for(int i=0;i<this->m_r;i++){
for(int j=0;j<this->m_c;j++){
if(grid[i][j]==1){
ir=i;ic=j;
return;
}
}
}
}();

This can simplify the code a lot since we do not need an extra function. If we do it in original cpp, we need to set a specific flag and check it in each for loop, and the code is redaundant in that case.

推荐文章