Ошибка сегментации для лямбда-функции в инициализаторе нестатических данных
Я не уверен в возможной ошибке GCC при инициализации std::function
из функции лямбда-захвата this
в инициализаторе нестатических данных. Разрешено ли это стандартом С++ или это 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
имеет значение null.
Следующие альтернативы работают так, как я ожидал:
-
Использование списка инициализаторов конструктора:
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.
Ответы
Ответ 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.
Ответ 2
Ваш код компилируется и запускается на 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
Итак, я думаю, что это ошибка