首页 > 解决方案 > 我无法从 C++ 中的函数式编程中重现函数记忆

问题描述

以下代码应该几乎是第 6 章第 1 节末尾的《C++ 函数式编程》一书的副本:

#include <iostream>
#include <utility>
#include <mutex>

template<typename F>
class lazy_val {
  private:
    F m_computation;
    mutable decltype(m_computation()) m_cache;
    mutable std::once_flag m_value_flag;
  public:
    lazy_val(F f)
        : m_computation(f)
    {}
    operator const decltype(m_computation())& () const {
        std::call_once(m_value_flag, [this](){
            m_cache = m_computation();
        });
        return m_cache; // the execution never gets to this line
    }
};

int expensive() {
    std::cout << "expensive call...\n";
    return 7;
}

int main() {
    std::cout << "non memoized" << '\n';
    std::cout << expensive() << '\n';
    std::cout << expensive() << '\n';
    std::cout << expensive() << '\n';
    const auto expensive_memo = lazy_val(expensive);
    std::cout << "memoized" << '\n';
    std::cout << expensive_memo << '\n'; // crash happens here
    std::cout << expensive_memo << '\n';
    std::cout << expensive_memo << '\n';
}

但是,当我执行它时(编译正常),我收到此错误:

non memoized
expensive call...
7
expensive call...
7
expensive call...
7
memoized
terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

如果忽略并发问题并且仅依赖于mutable bool m_cache_initialized;初始化为false和 a if (!m_cache_initialized) { m_cache = m_computation(); m_cache_initialized = true; },那么一切正常。

这让我认为问题在于我如何在代码中使用std::call_once/ 。std::once_flag但是我看不出它与书中显示的有什么不同(清单 6.2 中的构造函数,但没有初始化m_cache_initializedto的行false,类的其余部分位于第 125 页的底部和第 126 页的顶部)。

标签: c++multithreadinggccruntime-errorstd-call-once

解决方案


您必须使用 Linux 和 gcc。此实现的“未记录”功能是任何使用任何线程相关内容的 C++ 代码都必须显式链接到-lpthread.

在编译(使用-std=c++17)并链接不使用-lpthread. 显示的代码运行良好,如果与-lpthread.


推荐阅读