C++ lamba使用

Moderm Effective C++ 条款31 第206提到了按引用捕获局部变量和函数形参时,如果lambda式的生命期依赖于局部变量和函数形参的生命期,需注意空悬引用的问题。

原书的例子不够直观,把它改写后进行说明。

 1 #include "pch.h"
 2 #include <iostream>
 3 #include <vector>
 4 #include <functional>
 5 
 6 using FilterContainer = std::vector<std::function<bool(int)>>;
 7 FilterContainer filter;
 8 
 9 void addDivisorFilter() {
10 
11     auto divisor = 5;
12     filter.emplace_back([&](int value) {
13         return value % divisor == 0; 
14     });
15     std::cout << divisor << std::endl;
16 }
17 
18 int main()
19 {
20     addDivisorFilter();
21     addDivisorFilter();
22     std::cout << &filter[0] << std::endl;
23     std::cout << filter[0](4) < <std::endl;  //Unexpected function calls
24     std::cout << &filter[1] << std::endl;
25     std::cout << filter[1](5) << std::endl; //Unexpected function calls
26 }
filter是一个筛选器函数(筛选5的倍数)集合,line23,预期输出0,因为4不是5的倍数。line23,预期输出1.
实际结果则是

箭头1指向的结果看起来正确,箭头2指向的结果不正确,但这两个结果其实都是未定义行为的结果,不符合预期。

跟踪代码如下:

红框部分显示divisor是个很大的负数,不是预期的数字5。所以两次lambda调用结果输出都是0。

问题就出在lambda引用了divisor这个局部变量,addDivisorFilter函数出了代码块后,divisor消亡,lambda指向了一个空悬的divisor引用,当调用lambda时,它里面的divisor是一个未知值。

用这个未知值来进行模计算,当然会出错了。

未完待续...

猜你喜欢

转载自www.cnblogs.com/japelly/p/10017615.html