当前位置:网站首页>Clause 31: avoid default capture mode
Clause 31: avoid default capture mode
2022-06-13 04:56:00 【CCSUZB】
C++11 There are two default capture methods in : By value or by reference . The default capture by value may fool you , Default capture by reference may result in dangling references .
Capturing by reference causes closures to contain references to local variables , Or it comes to definitions lambda A reference to a formal parameter within the scope of a formula , Consider the following code :
using FilterContainer = std::vector<std::function<bool(int)>>;
FilterContainer filters;
void addDivisorFilter() {
auto calc1 = computeSomeValue1();
auto calc2 = computeSomeValue2();
auto divisor = computeDivisor(calc1, calc2);
filters.emplace_back( // dangerous , Yes divisor The reference of may be suspended !
[&](int value){
return value % divisor == 0;}
);
}
The above code can go wrong at any time ,lambda Formula refers to local variables diviisor References to , But this variable is in addDivisorFilter It does not exist on return . Even if not , Instead, capture by reference in a display way divisor, The problem remains.
filters.emplace_back( // dangerous , Yes divisor The reference of may be suspended !
[&divisor](int value){
return value % divisor == 0;}
One way to solve this problem is to use capture by value :
filters.emplace_back(
[=](int value){
return value % divisor == 0;}
Enough for this example ; But the problem is : After capturing by value A pointer after , stay lambda The closure created by the formula holds a copy of the pointer , But you can't stop lambda Code other than implements... For this pointer delete Null pointer copy caused by operation ;
Consider the following code :
class widget {
public:
void addFilter() const;
private:
int divisor;
};
void widget::addFilter() const
{
filters.emplace_back([=](int value){
return value % divisor == 0;});
}
Capture can only be made for when creating lambda Non static local variables visible to the scope of an expression ( Including formal parameters ). stay wdiget::addFilter In the function body of ,divisor Not a local variable , It is widget Member variables of class . It can't catch at all . In this way , If the default capture mode is eliminated , Code can't be Compile :
void widget::addFilter() const
{
filters.emplace_back([](int value){
return value % divisor == 0;}); // error ! There is nothing to capture divisor
}
If you try to display a capture divisor, This capture statement cannot be compiled , because divisor Not a local variable , Nor is it a formal parameter
void widget::addFilter() const
{
filters.emplace_back([divisor](int value){
return value % divisor == 0;}); // error ! There is nothing to capture divisor
}
Consider the following code :
using FilterContainer = std::vector<std::function<bool(int)>>;
FilterContainer filters;
void doSomeWork() {
auto pw = std::make_unique<Widget>();
pw->addFilter();
// ... Widget Be destroyed ,filter Now hold the dangling pointer
}
call doSomeWork Created a filter function , Depend on std::make_unique Created Widget object , The function is to filters in , However, when doSomeWork After execution ,Widget An object is the one that manages its life cycle std::unique_ptr The destruction . From that moment on ,filter Contains an element with a null pointer . This problem can be solved by copying the member variables you want to capture into local variables , Then capture the local variable to solve :
void Widget::addFilter() const {
auto divisorCopy = divisor; // Copy member variables
filter.emplace_back(
[divsorCopy](int value) // Capture copy
{
return value % divisorCopy == 0}; // Use copy
)
}
边栏推荐
- Crawler scrapy framework learning 2
- Force buckle 92 Reverse linked list II
- E - Lucky Numbers
- 2022道路运输企业安全生产管理人员操作证考试题库及答案
- What is the saturate operation in opencv
- QT client development -- driver loading problem of connecting to MySQL database
- 无限循环滚动代码阿里巴巴国际站店铺装修代码底图滚动黑色半透明显示效果自定义内容装修代码全屏显示
- PowerShell plus domain add computer module
- Analysis on the usage, response and global delivery of provide/inject
- Serial communication learning
猜你喜欢

Cesium:CesiumLab制作影像切片与切片加载

What is the difference between ROM, ram and flash? SRAM、DRAM、PROM、EPROM、EEPROM

Avantages de win8.1 et win10

Win8.1和Win10各自的优势

Embedded hardware: electronic components (1) resistance capacitance inductance

SQL notes

Simple-SR:Best-Buddy GANs for Highly Detailed Image Super-Resolution论文浅析

Ruoyi cloud startup tutorial (hand-held graphics)

What is the saturate operation in opencv

Section 5 - Operator details
随机推荐
PowerShell plus domain add computer module
Blockly learning ----1 Work area, block, toolbox
About mission planning and improving execution
Explain the differences and usage scenarios between created and mounted
Several methods of identifying equivalent circuit of circuit drawing
Tita performance treasure: remote one-on-one discussion
小C的记事本
第三方评论插件
ES6 learning
约瑟夫问题
Converting MySQL data to PostgreSQL with Navicat
Section 7 - structures
Section 3 - functions
Simple-SR:Best-Buddy GANs for Highly Detailed Image Super-Resolution论文浅析
Use go to add massive data to MySQL
All blog navigation
Third party comment plugin
How to lay copper in AD (aluminum designer)
Optocoupler working principle function electric parameter application circuit
On switch() case statement in C language