c++ - 将 Lambda 存储在类段错误中

标签 c++ lambda

这是我的程序的精简版,用于说明问题:

#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/

相关文章:

c++ - 是否可以只使用 function-member 属性创建回调接口(interface)?

c++ - lambda 表达式语法错误

Haskell 映射函数和 lambda 表达式

c# - delegate 关键字与 lambda 表示法

c# - 存在于列表中的 lambda 表达式

c++ - 单元测试 - 设置私有(private)成员以获得所需的对象状态

c++ - 键相等时 std::multimap 的自定义比较函数

c++ - tcp 连接上的 recv() 问题

c++ - #import 等效命令行

c# - 使用带有 lambda 表达式的 linQ 删除记录