我正在考虑某个解决方案,我想初始化在其他模块中定义的数组的单元格(将有许多模块初始化一个表)。在运行main之前不会读取数组(因此静态初始化顺序没有问题)。
我的方法:
/* secondary module */
extern int i[10]; // the array
const struct Initialize {
Initialize() { i[0] = 12345; }
} init;
/* main module */
#include <stdio.h>
int i[10];
int main()
{
printf("%d\n", i[0]); // check if the value is initialized
}
编译器不会删除init
常量,因为构造函数有副作用。我对吗?机制好吗?在海湾合作委员会(-O3)一切都很好。
// EDIT
在现实世界中,将有许多模块。 我想避免使用额外的模块,这是一个集中所有次要初始化程序的中心位置(为了更好的可扩展性)。因此,每个模块触发自己的初始化非常重要。
答案 0 :(得分:3)
这适用于MSVC编译器,但GNU C ++没有(至少对我来说)。 GNU链接器将删除编译单元外未使用的所有符号。我只知道保证这种初始化的一种方法 - “init once”成语。例如:
init_once.h:
template <typename T>
class InitOnce
{
T *instance;
static unsigned refs;
public:
InitOnce() {
if (!refs++) {
instance = new T();
}
}
~InitOnce() {
if (!--refs) {
delete instance;
}
}
};
template <typename T> unsigned InitOnce<T>::refs(0);
unit.h:
#include "init_once.h"
class Init : public InitOnce<Init>
{
public:
Init();
~Init();
};
static Init module_init_;
secondary.cpp:
#include "unit.h"
extern int i[10]; // the array
Init::Init()
{
i[0] = 12345;
}
...
答案 1 :(得分:0)
修改强>
/*secondary module (secondary.cpp) */
int i[10];
void func()
{
i[0]=1;
}
/*main module (main.cpp)*/
#include<iostream>
extern int i[];
void func();
int main()
{
func();
std::cout<<i[0]; //prints 1
}
使用g++ secondary.cpp main.cpp -o myfile
通常,使用(并且应该使用)构造函数来初始化类的成员。
答案 2 :(得分:0)
我认为您不希望主模块中的extern int i[10];
,adf88。
答案 3 :(得分:0)
这可能会奏效,但这很危险。单个模块中的全局/静态构造顺序是未定义的,模块加载顺序也是如此(除非您明确地管理它)。例如,假设在secondary.c Initialize()ctor运行期间,我已经存在。您必须非常小心,不要让两个模块初始化相同的公共数据,或者让两个模块执行具有重叠副作用的初始化。
我认为解决这种需求的更简洁的设计是让公共数据的所有者(您的主模块)将其公开为全局单例,并使用接口来执行所需的任何数据初始化。你有一个控制init-order的中心位置,甚至可能控制并发访问(使用关键部分或其他并发原语)。按照简化示例的说明,可能是 -
/ 主模块(main.c) /
的#include class CommonDat { int i;
public:
const int GetI() { return i;}
void SetI(int newI) { i = newI; }
void incI()
{
AcquireSomeLock();
i++;
ReleaseTheLock();
}
}
CommonDat g_CommonDat;
CommonDat* getCommonDat() { return &g_CommonDat; }
int main(void)
{
printf("%d",getCommonDat()->GetI());
}
最好让辅助模块在运行时的受控时间调用这些接口(并且在全局c'tors传递期间不)。
(注意:您将文件命名为C文件,但将问题标记为c ++。建议的代码当然是c ++。)
答案 4 :(得分:0)
当你可以使用std::vector
时,我可以问你为什么要使用数组(冒着越界的风险)?
std::vector<int>& globalArray()
{
static std::vector<int> V;
return V;
}
bool const push_back(std::vector<int>& vec, int v)
{
vec.push_back(v);
return true; // dummy return for static init
}
在第一次调用函数时,这个数组被懒惰地初始化。
您可以像这样使用它:
// module1.cpp
static bool const dummy = push_back(globalArray(), 1);
// module2.cpp
static bool const dummy = push_back(globalArray(), 2);
它似乎更容易,更不容易出错。它直到C ++ 0x才符合多线程。