为什么我的lambda按值捕获指针?

时间:2017-02-24 09:33:11

标签: c++11 lambda

我有以下lambda

    direction->addClickEventListener([=](Ref* sender){

        std::unordered_map<int,int> data;
        rep->getData(DIRECTION, data);
        int last = data[1];
        int rotation = (last + 45)%360;

        LOG("l:%i r:%i",last,rotation);//Always logs l:0 r:45
        direction->setRotation(rotation);
        data[1] = rotation;
        rep->setData(DIRECTION, data);
    });

其中getData是:

void getData(DATA_KEY key,std::unordered_map<int,int>& data){
//Modifies data with the appropriate values for key, for the current state of rep
}

void setData(DATA_KEY key,std::unordered_map<int,int>& data){
//Makes a copy of data stores it internally with key
}

rep是指针,所以我认为每当调用lambda时,数据的当前值将始终反映rep的当前状态。但似乎它始终是时间方向上任何代表的价值 - &gt; addClickEventListener被调用。

如果我想使用当前的rep状态,我修改lambda的食尸鬼怎么样? 编辑:由于rep是指针,我无法通过引用捕获..

2 个答案:

答案 0 :(得分:3)

我不确定你问的是什么,所以这可能不是你问题的答案,但它试图澄清通过引用捕获的问题是什么。

看起来你有一个基于事件的系统。关于事件的重要事项是它们可以随时发生。

现在假设你有这样的东西(非常简化和伪ish):

void some_function(some_type* rep)
{
    add_event_listener([&]()
    {
        do_something(rep);
    });
}

上面的代码中存在一个非常严重的错误:当调用事件并调用lambda时,函数some_function将返回,因此 局部变量的范围 rep不再存在。因此,当在lambda中使用rep时,它是对不再存在的变量的引用(请记住rep本地变量)。这当然会导致未定义的行为

如果按值捕获,则指针被复制意味着您现在有两个指针变量,两者都指向同一个内存。然后,如果第一个变量超出范围,则无关紧要,因为第二个变量仍然有效。

答案 1 :(得分:1)

指针没有状态,方法或其他东西。指针是您的对象所在的存储的抽象地址。 “引用”在某些方面与指针同义,如果你用C语言思考,但它们在C ++中是不同的 - 你可以通过引用传递指针变量,从而将控制传递给它的值(而不是它指向的对象状态,实际上是由指针实现的)。指针变量也是一个存储,它包含指针的值 您可以“通过引用”传递任何变量(存储),这意味着该函数可以更改存储在该变量中的值。在通过传递指针完成的C中,但是为了“通过引用”传递指针,它们必须将类似void**指针的类型传递给指针。在C ++&amp;语法用于减少混乱。

  • [=]勒芒所有外部变量都是按值捕获的。这将允许匿名函数读取指针的值,对它进行处理,并调用它指向的对象的方法\访问字段。

  • [&]意味着通过引用捕获。指针是可变的。这将允许lamba修改它,使其指向其他对象。

如果您确实只需要参考使用代表,[=。 &安培;代表。 lambda运行时如何更改rep?如果在并行线程中发生这种情况,您可能需要一个原子。

如果你不能改变指针引用的实际对象,这可能意味着编译器会因为从一个对象到另一个对象的非法转换而进行别名优化,因为转换了const修饰符或低质量的实现(很少见)会导致别名优化不应该发生的地方。