围绕递归函数的λ包装这个指针捕获(This-pointer capture in lambda wr

2019-07-18 10:17发布

我有一个类模板Wrap<T>用一个递归成员函数test(int)我想传递给一个拉姆达(STL的算法std::accumulate在下面的代码)。

如果我使用的默认捕获列表= ,使我的递归函数meber static ,一切都很好,并得到我想要的结果。

但是,如果我让一个非静态成员函数,既Visual C ++和GCC 4.7.2抱怨的未初始化this终场前,除非我有资格我的递归调用为this->test()

#include <algorithm>
#include <iostream>
#include <vector>

template<typename T>
struct Wrap 
{
   static int test1(int depth)
   {
      std::vector<int> v = { 0, 1, 2, 3 };
      return depth == 0? 1 : std::accumulate(v.begin(), v.end(), int(0), [=](int sub, int const&) {
         return sub + test1(depth - 1);
      });   
   }

   int test2(int depth)
   {
      std::vector<int> v = { 0, 1, 2, 3 };
      return depth == 0? 1 : std::accumulate(v.begin(), v.end(), int(0), [=](int sub, int const&) {
         return sub + /*this->*/test2(depth - 1);
      });   
   }   
};

int main()
{
   std::cout << Wrap<int>::test1(0) << "\n"; // 1
   std::cout << Wrap<int>::test1(1) << "\n"; // 4
   std::cout << Wrap<int>::test1(2) << "\n"; // 16

   Wrap<int> w;
   std::cout << w.test2(0) << "\n"; // 1
   std::cout << w.test2(1) << "\n"; // 4
   std::cout << w.test2(2) << "\n"; // 16
}

输出LiveWorkSpace :

source.cpp: In instantiation of 'int Wrap<T>::test2(int) [with T = int]':   
source.cpp:32:26:   required from here 
source.cpp:19:74: error: missing initializer for member 'Wrap<T>::test2(int) [with T = int]::<lambda(int, const int&)>::__this' [-Werror=missing-field-initializers]

在取消对/*this->/*件,给出相同的结果作为用于静态成员函数。

我为什么要限定我的递归调用与this->

Answer 1:

我相信这是GCC 4.7.2的一个bug。 警告说:

missing initializer for member 'Wrap<T>::test2(int) [with T = int]::<lambda(int, const int&)>::__this'

这意味着,编译器可识别this指针将被捕获并产生闭合确实包含一个指针,但该指针不会在封闭的构造函数初始化得到。

这是由以下事实试图访问/改变一个成员变量(其不存在于你的例子,但可以容易地添加)证实导致运行时错误。 例如,这显示了在liveworkspace.org没有输出

#include <algorithm>
#include <iostream>
#include <vector>

template<typename T>
struct Wrap 
{
    int test2(int depth)
    {
        m_test++;
        std::vector<int> v = { 0, 1, 2, 3 };
        return depth == 0? 1 : std::accumulate(
             v.begin(), v.end(), int(0), [=](int sub, int const&) {
             return sub + /*this->*/test2(depth - 1);
             });   
    }

    int m_test = 0;
};

int main()
{
    Wrap<int> w;
    std::cout << w.test2(2) << "\n"; // 1
}

此代码编译罚款锵3.2和VS2012,这似乎也印证了一个错误的存在。



文章来源: This-pointer capture in lambda wrapper around recursive function