简体   繁体   English

c + + 11按值捕获lambda产生错误的值

[英]c++11 capture-by-value lambda producing wrong value

I'm trying to store a lambda in an object system involving several layers of indirection. 我正在尝试将lambda存储在涉及多个间接层的对象系统中。 I'm using g++ 4.7.1. 我正在使用g ++ 4.7.1。

Depending on how exactly I construct the (equivalent) objects, the lambda may or may not have the correct value. 根据我构造(等效)对象的精确程度,lambda可能具有也可能没有正确的值。

Code: 码:

#include <iostream>
#include <functional> // used for std::function

using namespace std; // TODO nope

typedef function<int()> intf;


struct SaveLambda {
    const intf func;
    SaveLambda(const intf& _func) : func(_func) {}  
};


struct StoreSaved {
    const SaveLambda* child;
    StoreSaved(const SaveLambda& _child) : child(&_child) {
        cout << "Before returning parent: " <<  child->func() << endl;
    }
};


int main() {
    const int ten = 10;

    auto S = SaveLambda([ten](){return ten;});
    cout << "No indirection: " << S.func() << endl << endl;

    auto saved = StoreSaved(S);
    cout << "Indirection, saved: " << saved.child->func() << endl << endl;

    auto temps = StoreSaved ( SaveLambda([ten](){cout << "&ten: "<< &ten << endl; return ten;}) );
    cout << "***** what. *****" << endl;
    cout << "Indirection, unsaved: " << temps.child->func() << endl;
    cout << "***** what. *****" << endl << endl;

    cout << "ten still lives: " << ten << endl;
}

Compile as g++ -std=c++11 -Wall -o itest itest.cpp and run: notice the one line of output with a different value. 编译为g++ -std=c++11 -Wall -o itest itest.cpp并运行:请注意输出的一行具有不同的值。

What am I doing wrong? 我究竟做错了什么? I assumed that capture-by-value would, well, capture by value. 我以为按价值捕获就可以按价值捕获。 (Observe most disconcertingly that the print in StoreSaved (line 15) produces the correct value, unlike line 34, despite these both referring to the same object. The only difference is adding another layer of indirection.) (最令人不安的是,请注意,StoreSaved(第15行)中的打印产生了正确的值,与第34行不同,尽管它们都引用同一个对象。唯一的区别是添加了另一层间接寻址。)

This is wrong: 这是错误的:

auto temps = StoreSaved(
                /* This temporary value dies at the last semicolon! */
                SaveLambda([ten](){cout << "&ten: "<< &ten << endl; return ten;})
                );

StoreSaved then has a pointer to a nonexistent object. 然后, StoreSaved具有指向不存在对象的指针。 Using it is UB. 使用它是UB。

As already pointed out by others, the problem is that in temps you end with a pointer to a nonexistent SaveLambda struct, as it is a temporary. 正如其他人已经指出的那样,问题是temps您最终会指向一个不存在的SaveLambda结构的指针。

You can keep a copy using a SaveLambda struct in StoreSaved, instead of a pointer: 您可以使用StoreSaved中的SaveLambda结构代替指针来保留副本:

struct StoreSaved {
   const SaveLambda child;
   StoreSaved(const SaveLambda& _child) : child(_child) {
       cout << "Before returning parent: " <<  child.func() << endl;
   }
};

You also have to change all the child->func() to child.func() , as you are not dealing with a pointer anymore. 您还必须将所有child->func()更改为child.func() ,因为您不再处理指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM