在C ++ 11 lambda中通过引用捕获静态变量 [英] Capturing a static variable by reference in a 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'这里声明
$ c $因此,我的第一个问题是:
这是一个失败的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),
[®istry] (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屋!