通过C++ 11 lambda中的引用捕获静态变量

Jos*_*uel 37 c++ lambda c++11

主要问题

我正在尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)

似乎进展不顺利,因为输出是这样的:

$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
Run Code Online (Sandbox Code Playgroud)

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

这是GCC的失败,还是代码不合法​​C++ 11?这在GCC的最新版本中是否已修复?

在shared_ptr工厂中使用技巧

我考虑使用非文字静态变量构建基于此原理的工件.此工件旨在成为shared_ptr <T>对象的工厂,当您只需要为同一实例使用重复的shared_ptr容器时,它可以避免创建新的T对象.

这个工件看起来像:

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;
}
Run Code Online (Sandbox Code Playgroud)

据我所知,如果之前讨论的GCC问题在C++ 11一致性方面不是问题,那么这个工件也不应该成为问题.使用此hack唯一要注意的是,不要将生成的shared_ptr <T>对象设置为可以在静态变量之后被破坏的任何全局对象.

我这是对的吗?

Lil*_*ard 83

为什么你甚至试图捕捉bar?这是静态的.您根本不需要捕获它.只需要捕获自动变量.Clang会对您的代码产生严重错误,而不仅仅是警告.如果您只是&bar从lambda捕获中删除,那么代码就可以完美运行.

#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;
}
Run Code Online (Sandbox Code Playgroud)

版画

0
1
2
Run Code Online (Sandbox Code Playgroud)


Don*_*nie 11

根据标准,您只能捕获具有自动存储持续时间的变量(或者this,它被提及为明确可捕获的).

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

5.1.1/2 lambda-capture中的名称应在lambda表达式的上下文中,并且应该是这个或引用具有自动存储持续时间的局部变量或引用.

编辑:而且,正如凯文所说,你甚至不需要捕捉当地人static.