非静态数据成员初始值设定项中lambda函数的分段错误

时间:2016-09-21 16:04:36

标签: c++ c++11 gcc language-lawyer

我不确定在非静态数据成员初始值设定项中捕获std::function的lambda函数初始化this时可能存在GCC错误。这是允许的C ++标准还是这个UB?

给出以下代码:

#include <functional>
#include <iostream>

template <typename T>
struct A {
      T x = 0;
      std::function<void(T)> f = [this](T v) { x = v; };
};

int main() {
      A<int> a;
      a.f(1);
      std::cout << a.x << "\n";
}

根据我的理解,它应该打印1。但是,使用GCC 5.4.0或GCC 6.2.0构建时,a.f(1)会发出分段错误,因为捕获的this指针为空。

以下备选方案按预期工作:

  • 使用构造函数初始化列表:

    template <typename T>
    struct B {
        B() : f([this](T v) { x = v; }) {}
        T x = 0;
        std::function<void(T)> f;
    };
    
  • 没有模板:

    struct C {
        int x = 0;
        std::function<void(int)> f = [this](int v) { x = v; };
    };
    

此外,当使用Clang 3.8.0构建时,所有三个版本都表现得如我所料,这并不意味着它不是UB。

2 个答案:

答案 0 :(得分:1)

你做不到:

template <typename T>
struct A {
    T x = 0;
    std::function<void(T)> f = [this](T v) { x = v; };
};

定义this时,f不存在。您需要在构造函数中初始化f,例如:

A(){ f = [this](T v){ x=v; } }

它适用于G ++ 4.8。

答案 1 :(得分:0)

您的代码在VS2015(windows)上编译并运行。 所以这可能是一个编译器错误。

此外,如果您要移除模板,则可以使用http://cpp.sh/ 试试这段代码:

#include <functional>
#include <iostream>

struct A {
      int x = 0;
      std::function<void(int)> f = [this](int v) { x = v; };
};

int main() {
      A  a;
      a.f(1);
      std::cout << a.x << "\n";
}

在cpp.sh上运行原始代码给出:

 internal compiler error: in tsubst_copy, at cp/pt.c:12569
Please submit a full bug report

所以我猜这是一个错误