在 main 之前使用来自不同文件的变量

Using a variable from a different file before main

我有点难以理解为什么我的代码按它的方式工作(或不按它应该的方式工作)。

我正在尝试编写(在 C++ 中)一个接口,该接口允许使用 C 中标准模板库中一些在 unordered_map 上运行的函数。但是,我还想编写一个名称空间也允许在 C++ 中使用它们。

我要问的不是如何以不同的方式处理它,而是为什么它会这样工作;

暂时说一下,我只需要两个功能:添加元素和写地图的大小。 header 如下:

//project.h
#ifdef __cplusplus
extern "C" {
#endif

void add(int, int);

void give_size();

#ifdef __cplusplus
}
#endif

源代码:

//project.cc
#include <unordered_map>
#include <iostream>
#include "project.h"

using namespace std;

unordered_map<int, int> my_map;

void add(int arg, int val) {
    my_map.insert ({{arg, val}});
}

void give_size() {
    cout << my_map.size() << endl;
}

C++ 接口:

//cproject
namespace pro {
    #include "project.h"
}

和一个测试:

//test.cc
#include "cproject"
namespace {
    unsigned long test() {
        ::pro::add(1,2);
        ::pro::add(3,4);
        return 0;
    }
    unsigned long dummy = test();
}
int main() {
    ::pro::give_size();
    return 0;
}

并且,为了完整起见,Makefile:

g++ -Wall -std=c++11 -c -o project.o project.cc
g++ -Wall -std=c++11 -c -o test.o test.cc
g++ test.o project.o -o test

当然,问题是 运行 test 输出 0 而不是 2 - 这意味着地图在 [=17= 之前的某处消失了]的main.

我认为它可能是某种 static initialization order fiasco,但是我发现附加的解决方案不是很有用,因为我没有明确地从 [=22= 中调用 objects ] 文件在 test.cc.

如果能帮助解决这个问题,我将不胜感激。

是的,这是命名不当的静态初始化顺序失败。命名不当,因为 C++ 标准称它为 "dynamic initialization"; "static initialization" 有点不同。

which means that the map disappears somewhere before the test's main

不完全是。问题是您在地图 存在 之前使用地图,向其添加值。现在碰巧对于某些 map 实现,零初始化状态(这是在任何动态初始化器 运行 之前对所有全局变量所做的)与默认构造函数所做的相同。所以test中的代码首先被执行并尝试向地图添加东西,地图的插入功能工作得很好,创建节点,设置节点的内部指针等

然后是映射 运行 的实际默认构造函数,将这些指针重置为空,泄漏并忘记您创建的所有节点。您之前的插入已撤消,地图再次为空。

您 link 中提供的解决方案可以工作;你通过自由函数隐式地调用对象,即使你没有明确地这样做。没有真正的区别。您仍然将 project.cc 中的全局 my_map 替换为 returns 对函数级静态(或指针,具体取决于您选择的确切解决方案)的引用的函数。唯一的区别是您不是从 test.cc 中调用此函数,而是从 addgive_size.

中调用此函数

附带说明一下,整个全局状态的事情通常相当可疑。它不是线程安全的,并且使理解程序正在做什么变得更加困难。考虑完全不这样做。