C++ 在成员函数内使用lambda捕获列表中的成员变量

C++ 在成员函数内使用lambda捕获列表中的成员变量,c++,visual-studio-2010,lambda,c++11,C++,Visual Studio 2010,Lambda,C++11,以下代码使用gcc 4.5.1编译,但不使用VS2010 SP1编译: #include <iostream> #include <vector> #include <map> #include <utility> #include <set> #include <algorithm> using namespace std; class puzzle { vector<vector<int&g

以下代码使用gcc 4.5.1编译,但不使用VS2010 SP1编译:

#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <set>
#include <algorithm>

using namespace std;
class puzzle
{
        vector<vector<int>> grid;
        map<int,set<int>> groups;
public:
        int member_function();
};

int puzzle::member_function()
{
        int i;
        for_each(groups.cbegin(),groups.cend(),[grid,&i](pair<int,set<int>> group){
                i++;
                cout<<i<<endl;
        });
}
int main()
{
        return 0;
}
所以

1> 哪个编译器是对的


2> 如何在VS2010中使用lambda中的成员变量?

我认为,您需要捕获

我认为VS2010这次是正确的,我会检查是否有现成的标准,但目前我没有

现在,这与错误消息所说的完全一样:您无法捕获lambda封闭范围之外的内容。†
网格
不在封闭范围内,但
在成员函数中(对
网格
的每次访问实际上都是作为
此->网格
进行的)。对于您的用例,捕获
这个
是可行的,因为您将立即使用它,并且您不想复制
网格

auto lambda = [this](){ std::cout << grid[0][0] << "\n"; }


†我正在简化-谷歌“达到范围”或参见§5.1.2了解所有血淋淋的细节。

限制lambda范围而不是让它访问整个
的另一种方法是将局部引用传递给成员变量,例如

auto& localGrid = grid;
int i;
for_each(groups.cbegin(),groups.cend(),[localGrid,&i](pair<int,set<int>> group){
            i++;
            cout<<i<<endl;
   });
auto&localGrid=grid;
int i;
对于每个(groups.cbegin()、groups.cend()、[localGrid,&i](对组){
i++;
备选方案概述:
捕获此

auto lambda = [this](){};
使用对成员的本地引用:

auto& tmp = grid;
auto lambda = [ tmp](){}; // capture grid by (a single) copy
auto lambda = [&tmp](){}; // capture grid by ref
C++14:

auto lambda = [ grid = grid](){}; // capture grid by copy
auto lambda = [&grid = grid](){}; // capture grid by ref

示例:

这是正确的,它将捕获This指针,您仍然可以直接引用
网格
。问题是,如果您想复制网格怎么办?这不允许您这样做。您可以,但只能以一种迂回的方式:您必须创建一个本地副本,并在lambda中捕获该副本。这只是lambdas的规则,您可以这样做无法捕获封闭范围之外的stiff。当然,您可以复制。我的意思是您当然不能复制捕获它。我所描述的是通过中间本地副本进行复制捕获-请参阅我的答案。除此之外,我不知道任何复制捕获成员变量的方法。当然,它进行复制捕获,但不捕获成员。它涉及两个副本除非编译器比平常更聪明,否则我猜。注意:它应该是
pair
,这是映射的实际pair类型。它可能还应该是对const.Related的引用;非常有用:它似乎对我来说非常有限。我不明白为什么编译器需要阻止这样的事情。它可以与bind一起工作,尽管语法很糟糕使用ostream左移位运算符执行ble。是否可以将
tmp
作为
常量&
网格
以减少复制?我们仍然需要至少一个副本,将副本复制到lambda(
[tmp]
),但不需要第二个副本。解决方案可能会制作一个不必要的额外的
grid
副本,尽管它可能会得到优化。更短更好的是:
auto&tmp=grid;
等等。如果您有可用的C++14,您可以做
[grid=grid](){std::cout它似乎在GCC4.9(和GCC5.4)中是固定的吗
错误:捕获非变量'puzzle::grid'
我喜欢你的想法:使用一个伪引用变量并将其传递给捕获列表:)有趣的是,只有显式使用带有初始值设定项语法的捕获才能实现这一点(即,在C++14中,仅仅执行
[&grid]
仍然不起作用)很高兴知道这个!很好的总结。我觉得C++14语法非常方便
auto& tmp = grid;
auto lambda = [ tmp](){}; // capture grid by (a single) copy
auto lambda = [&tmp](){}; // capture grid by ref
auto lambda = [ grid = grid](){}; // capture grid by copy
auto lambda = [&grid = grid](){}; // capture grid by ref