在C ++ 11 lambda中通过引用捕获静态变量 [英] Capturing a static variable by reference in a C++11 lambda

查看:1094
本文介绍了在C ++ 11 lambda中通过引用捕获静态变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

主要问题



我试图使用GCC 4.7.2编译以下代码:

  #include< iostream> 

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

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

看起来不太好,

  $ p2.cpp:在函数'int foo()':
$ p2.cpp:6:14 :warning:捕获带有非自动存储持续时间的变量'bar'[默认情况下启用]
$ p2.cpp:4:16:note:'int bar'这里声明


这是一个失败的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>注册表;

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一致性方面,这个工件不应该是一个问题。使用这个黑客唯一需要注意的是不要设置产生的shared_ptr<



解决方案

为什么你甚至试图捕获 bar ?它是静态的。你不需要捕捉它。只有自动变量需要捕获。 Clang在代码上引发了一个硬错误,而不仅仅是一个警告。如果你简单地从你的lambda捕获中删除& bar ,那么代码可以完美地工作。

  #include< iostream> 

int foo(){
static int bar;
return [](){return bar ++; }(); // lambda capture 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


Main question

I'm trying to compile the following code with 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;
}

And it seems that is not going well, as the output is this one:

$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

So, my first question would be:

Is this a failure of GCC, or the code is not legit C++11? Is this fixed in any recent version of GCC?

Using the trick in a shared_ptr factory

I consider to build an artifact based on this principle but using a non-literal static variable. This artifact is meant to be a factory of shared_ptr< T > objects, which avoid the creation of new T objects when you just need a duplicate shared_ptr container for the same instance.

This artifact would look like:

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;
}

As far as I know, if the GCC issue discussed before is not a problem in terms of C++11 conformance, this artifact shouldn't be an issue either. The only thing to take care by using this hack, is to not set the resulting shared_ptr< T > object to any global object which could be destructed after the static variable.

Am I right about this?

解决方案

Why are you even trying to capture bar? It's static. You don't need to capture it at all. Only automatic variables need capturing. Clang throws a hard error on your code, not just a warning. And if you simply remove the &bar from your lambda capture, then the code works perfectly.

#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;
}

prints

0
1
2

这篇关于在C ++ 11 lambda中通过引用捕获静态变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆