考虑一下这个例子:
#include <iostream>
#include <functional> // std::function
#include <vector> // std::vector
#include <algorithm> // std::for_each
int main(){
auto adder = [](int x) {
return [&](int y) {
return x+=y;
};
};
std::vector < std::function<int(int)> > vec;
vec.push_back(adder(1));
vec.push_back(adder(10));
std::for_each(vec.begin(), vec.end(), [](std::function<int(int)> f){std::cout << f(33) << " ";});
std::cout << std::endl;
}
一个人期望整数 34和43 43 和 76 ,但gcc 4.6.0会产生“内部编译器错误:分段错误” 。代码有什么问题?
编辑:讨论了其他几个例子here。
答案 0 :(得分:2)
(编辑:这当然不能解释ICE;我太匆忙地读了原来的问题。)
该代码中的 一个问题是从adder
函数返回的lambda包含对x
变量的悬空引用,不再存在。通过副本([=]
或[i]
)而不是引用([&]
)进行捕获,一切都应该有效。
答案 1 :(得分:0)
看来,在你的例子中,trailing-return-type不能省略。以下是标准(5.1.2 Lambda表达式)的摘录:
如果lambda表达式没有 包括尾随返回类型,它是 好像尾随返回类型表示 以下类型: - 如果compound-statement的格式为{attribute-specifier-seq return expression; lvalue-to-rvalue转换(4.1),数组到指针转换(4.2)和函数到指针转换(4.3)之后返回表达式的类型; - 否则,无效。
示例中的返回值不能用于上述转换。以下代码在VS 2010中明确添加了返回类型编译:
auto adder = [] (int x) -> std::function<int (int)> {
return [=]( int y ) {
return x + y;
};
};
答案 2 :(得分:0)
你只是完全忽略了这一点。对std::function
的需求非常非常明显。
std::function
所做的。你到底怎么能创建一个在运行时变化的编译时事实,就像它包含的类型一样?这在逻辑上是不可能的 - 除非你使用诸如std::function
之类的抽象。
当然,如果您只想要一个lambda类型,那么您根本不需要std::function
。但这种情况相对较少。
int main() {
auto adder = [](int x) {
return [=](int y) {
return x + y;
};
};
// alternatively- you MUST copy the argument as it will cease to exist
// but once it's in the lambda, you can use "mutable" to allow you to
// modify the copy that each lambda has.
/*
auto adder = [](int x) {
return [=](int y) mutable {
return x += y;
};
};
*/
std::vector<decltype(adder(0))> adders;
adders.emplace_back(adder(0));
adders.emplace_back(adder(1));
std::for_each(adders.begin(), adders.end(), [](decltype(*adders.begin())& ref) {
std::cout << ref(33);
});
std::cin.get();
}
MSVC实际上不会编译这个小片段,但我认为这是一个错误并且根据编译器的报告来判断,我希望它会在那里编译并确实正常工作。