我可以编写一个库,以便在加载时首先生成一个数据集,该数据集稍后可以被其他函数访问吗?

Could I write a library such that when loaded it first generates a dataset which could later be accessed by other functions?

通常库的函数只在调用时执行(不像普通程序有像 main() 这样的入口点),但在这种情况下,我想发布一个需要数据集的库,数据集太大,最好自己生成。

这让我想知道我是否可以编写一个库,在加载时执行一个生成数据集的函数(可能保存在全局变量或 extern 变量中),以后可以被其他函数使用,类似以下内容:

// lib.hh
#pragma once
struct Data{}; // Data is a custom class for holding the data set
extern Data dataset;
// lib.cc
#include"./lib.hh"
Data gen() {
    // Generates the data here
    return result;
}
double find(double key) {
    // Searches data within `dataset` that has `key` as its key
}

所以当在另一个程序中加载时,gen() 应该自动 运行(并且在任何其他函数之前),然后加载库的程序可以调用 find(double)

这样的库实现可行吗?或者我最好只召唤一个生成数据的子进程,然后通过管道检索结果?

对于这种情况,我建议使用 static 局部变量

//header
struct Data{
Data() {
//Complex intialization code goes here
}
};


Data& data_gen() {
    static Data data;
    return data;
}

//caller/main
auto Data = data_gen(); //Initialization code run once
auto Data2 = data_gen(); //Reuse the variable no more runs

即使不同的线程也可以调用那个 data_gen 函数,但当然他们应该只读它,不要写不同步的东西。所以我通常会给它一个 const 引用,因为共享可变数据,即通过全局变量的状态是非常非常糟糕的风格。 所以更喜欢

const Data& data_gen() {
    static Data data;
    return data;
}

但是尽管这种方法是最稳健的方法,通常你可以在主函数 运行 之前让它 运行,如果你是所谓的静态链接(classic/default/standardized C++ 中的方式),但如果你是 .so/.dll/.dylib 就不行:

//Header lib.hpp
#pragma once
#include <iostream>
namespace lib_name {

    struct Data{
        Data() {
            std::cout << "Ctor\n";
        }
        double find(double key) const{
            return 0;
        }
    };
    extern const Data dataset;

    void foo();
}

//lib.cpp
#include <lib.hpp>

namespace lib_name {
    const Data dataset;

    void foo() {
        dataset.find(5);
    }

}
//main
#include <lib.hpp>
int main() {
    lib_name::dataset.find(4.2);
    lib_name::dataset.find(4.2);
    lib_name::foo();
}

你只会得到一个“Ctor”,在 main 之前,但如果你的数据生成很复杂但可以用 std::array 完成,为什么不让它更简单呢?

//header
#include <array>

namespace lib_name {

    struct Data{
        constexpr Data() {
            d_[0] = 42;
        }
        double find(size_t key) const{
            return d_.at(key);
        }

        std::array<double,5> d_{};
    };
    inline constexpr Data dataset;

    void foo();//just for demonstration optional of course
}

//lib.cpp optional
#include <lib.hpp>
#include <iostream>
namespace lib_name {
    void foo() {
        std::cout << dataset.find(0) << "\n";
    }
}

然后你的初始化代码是运行一次,但是被编译器编译了。然后它只保存结果。