在C ++ 11中使用lambda默认捕获值或引用的缺点?

时间:2016-01-02 16:41:07

标签: c++ lambda

在C ++ 11中使用lambda默认捕获值([=])或引用([&])会有什么陷阱?

我知道一些陷阱:

  • 如果从lambda创建的闭包的生命周期超过了局部变量的生命周期,则闭包中的引用将悬空?

按值划分的默认值是否有任何缺点?

4 个答案:

答案 0 :(得分:7)

我认为你提到的悬空参考问题是主要的陷阱。

有时候忽略的另一件事是,即使在成员函数中使用了按值捕获的lambda,它也不会创建使用过的成员变量的副本,但只能创建一个this指针的副本。

首先,这意味着你再次对悬空指针问题开放问题,其次,你可能会意外地修改lambda范围之外的变量,即使看起来像,你只是在修改本地副本。

E.g。这将打印0 1 1而不是0 1 0

struct Foo {
    int bar=0;
    int bas() {
        auto inc = [=]() {          
            bar++;  //this is equivalent to this->bar++ 
            return bar; 
        };
        return inc();
    }
};

int main() {
    Foo foo;
    std::cout << foo.bar <<" ";
    std::cout << foo.bas() << " ";
    std::cout << foo.bar << std::endl; 
}

编辑: 只是为了避免与@Snps所提出的观点相混淆:
如果barbas()中的局部变量(因此被值捕获),则上述lambda将无法编译,因为by-value-captured-variables默认为const,除非您明确指定lambda是可变的。 因此,如果您考虑一下,很明显条形图不会被复制,但在阅读或编写代码时很容易被遗忘。

答案 1 :(得分:3)

与以下方面的比较具有完全相同的优点和缺点:

int value(const T x) { ... }
int value(T& x) { ... }

答案 2 :(得分:3)

使用 hbspt.forms.create({ css: '', cssClass:'.hs-form fieldset {max-width: 100%;}', portalId: '', formId: '', inlineMessage: '<iframe style="width:100%; height:800px;" scrolling="auto" src="URL goes here"></iframe>', onFormSubmit: function(){ mmConversionTag(704048, this, "_self"); ga("send","event","button","click","product distributors"); } }); [=]按值捕获可以创建与捕获的实体完全相同的的lambda成员,包括constness 例如,当按值捕获[<identifier>]时,即使lambda调用运算符是可变的,结果成员也可以变异。

const int

这可以使用C ++ 14初始化捕获表达式来解决:

const int i = 1;
[=] () mutable { ++i; }(); // Error: increment of read-only variable.

答案 3 :(得分:1)

按值捕获涉及复制关闭的值,因此可能意味着更多的内存消耗和对该副本的更多处理。