这是我的程序的精简版,用于说明问题:
#include <functional>
#include <iostream>
template<class T>
class Piped {
public:
typedef T value_type;
};
template<class P1, class P2, class T>
class PipeConnector : public Piped<T> {
public:
PipeConnector(const P1 &p1, const P2 &p2)
: m_1(p1), m_2(p2) { }
bool run(const T &element) const {
return m_1.run(element) || m_2.run(element);
}
private:
const P1 &m_1;
const P2 &m_2;
};
template<class T>
class NullOp : public Piped<T> {
public:
bool run(const T&) const {
return false;
}
};
template<class T, class Functor>
class FunctionOp : public Piped<T> {
public:
FunctionOp(Functor f1)
: m_1(f1) { }
bool run(const T &element) const {
return m_1(element);
}
private:
std::function<bool(T)> m_1;
};
template<class P1, class Functor>
auto operator|(const P1 &p1, const Functor &f2) {
return PipeConnector<P1,
FunctionOp<typename P1::value_type, std::function<bool(typename P1::value_type)>>, typename P1::value_type>(
p1, FunctionOp<typename P1::value_type, std::function<bool(typename P1::value_type)>>(f2));
}
int main() {
auto p = NullOp<int>() | [](int x) -> bool { if (x < 10) { return true;} return false; };
std::cout << p.run(20) << std::endl;
return 0;
}
使用 g++/clang++ -std=c++14 编译此程序会导致段错误。将 -O3 添加到其中,使其运行时不会出现段错误。
当将 PipeConnector 更改为不存储 const 引用但存储拷贝时,这是有效的。我认为问题是一些 lambda 范围问题,但我不明白出了什么问题。 -O3 似乎忽略了这个问题?你能给我解释一下这个问题吗?
最佳答案
问题是 NullOp<int>()
是一个临时文件,您可以在其中存储一个常量引用 PipedConnector
.此临时文件具有完整的表达式生命周期,因此在 p
之后不存在已经初始化。当您调用 p.run(20)
然后您再次引用该临时文件,该临时文件已被删除。由此产生的 UB 可能会导致崩溃。
关于c++ - 将 Lambda 存储在类段错误中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30461093/