静态变量的初始化顺序未定义,因此它取决于您的特定设置,包括编译器,链接器和链接顺序.
初始化函数技巧
您可以使用初始化函数技巧来确保在需要时初始化某些内容.我知道这可以在Windows上使用Microsoft的C编译器(并且在Linux上对g进行了一些测试,见下文).
初始化函数
第一步是将地图作为静态变量移动到一个函数中,并始终通过此函数访问地图.
buttonmap_t& buttonMap() {
static buttonmap_t map;
return map;
}
用法
首次调用buttonMap()函数时会创建映射.如果您通过该功能访问地图,那么您可以确定它将被创建.
Controller::Button::Button(int type) :
type_(type) {
buttonMap()[type] = this;
}
关键部分是全局变量的初始化:用引号替换它并从保存变量的函数初始化它.
buttonmap_t& map = buttonMap();
说明
使用此设置初始化顺序无关紧要,因为对函数的第一次调用将执行初始化,并且每次调用之后将使用初始化实例.
注意:此技巧适用于全局变量,因为初始化阶段是在单个线程上完成的.即使您不知道初始化的确切顺序,也可以确保它将按顺序发生.
测试
我在我的家用电脑上使用g在Linux上进行了测试,它似乎有效:
$g++ main.cpp controller.cpp -Wall
$./a.out
running...
最终计划:
// controller.h
#ifndef CONTROLLER_H
#define CONTROLLER_H
class Controller {
public:
class Button {
public:
Button(int type = -1);
private:
int type_;
};
Controller();
Button A;
Button B;
Button X;
Button Y;
};
#endif
// controller.cpp
#include "controller.h"
#include
typedef std::map buttonmap_t;
buttonmap_t& ButtonMap() {
static buttonmap_t map;
return map;
}
buttonmap_t& map = ButtonMap();
Controller::Controller() :
A(0),
B(1),
X(2),
Y(3) {
}
Controller::Button::Button(int type) :
type_(type) {
ButtonMap()[type] = this;
}
// main.cpp
#include "controller.h"
#include
Controller controller;
int main(int argc, const char * argv[]) {
std::cout << "running..." << std::endl;
return 0;
}