通过在C ++ 11拉姆达参考捕获一个静态变量(Capturing a static variabl

2019-07-04 23:25发布

主要问题

我试图用GCC 4.7.2编译下面的代码:

#include <iostream>

int foo() {
    static int bar;
    return [&bar] () { return bar++; } (); // lambda capturing by reference
}

int main (int argc, char* argv[]) {
    std::cout << foo() << std::endl;
    return 0;
}

它似乎并不顺利,因为输出是这一个:

$p2.cpp: In function ‘int foo()’:
$p2.cpp:6:14: warning: capture of variable ‘bar’ with non-automatic storage duration [enabled by default]
$p2.cpp:4:16: note: ‘int bar’ declared here

所以,我的第一个问题是:

这是GCC的故障或代码是不合法的C ++ 11? 这是固定在任何最新版本的GCC?

在一个shared_ptr的工厂使用的伎俩

我认为基于这个原理,但使用非字面静态变量建立一个神器。 这神器,就是要的shared_ptr <T>对象,避免新的T对象的创建时,你只需要为同一个实例重复的shared_ptr容器的工厂。

这神器将如下所示:

std::shared_ptr<Foo> create(std::string name) {
    static std::unordered_map<std::string,std::weak_ptr<Foo>> registry;

    if (auto it = registry.find(name) != registry.end())
        return registry[name].lock();

    auto b = std::shared_ptr<Foo>(
        new Foo(name), 
        [&registry] (Foo* p) {
            registry.erase(p->getName());
            delete p;
        });

    registry.emplace(name,b);
    return b;
}

据我所知,如果之前讨论的GCC问题是不是在C ++ 11的一致性方面存在问题,这件神器不应该是问题。 通过使用本hack照顾的唯一事情,是向所得的shared_ptr <T>对象未设置为这可能静态变量后遭到破坏任何全局对象。

我说的对这个吗?

Answer 1:

为什么你甚至试图捕捉bar ? 它是静态的。 你并不需要捕获它。 只有自动变量需要捕获。 锵抛出您的代码,不只是一个警告硬错误。 如果你只是删除&bar从拉姆达捕获,然后将代码完美的作品。

#include <iostream>

int foo() {
    static int bar;
    return [] () { return bar++; } (); // lambda capturing by reference
}

int main (int argc, char* argv[]) {
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    return 0;
}

版画

0
1
2


Answer 2:

按照标准,你只能捕捉自动存储时间(或变量this ,这是因为明确提到可拍摄)。

所以,不,你不能这样做,按照标准(或者,要回答你的第一个问题,是无效的C ++ 11,而不是一个编译器错误)

5.1.1 / 2在λ-捕获的名称应在lambda表达式的上下文范围内,并应为本或指一个局部变量或参考与自动存储持续时间。

编辑:而且,正如凯文提到的,你甚至都不需要捕捉本地static反正。



文章来源: Capturing a static variable by reference in a C++11 lambda
标签: c++ c++11 lambda