部分初始化其他模块中定义的变量

时间:2010-07-06 15:35:10

标签: c++ optimization compiler-construction static initialization

我正在考虑某个解决方案,我想初始化在其他模块中定义的数组的单元格(将有许多模块初始化一个表)。在运行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
在现实世界中,将有许多模块。 我想避免使用额外的模块,这是一个集中所有次要初始化程序的中心位置(为了更好的可扩展性)。因此,每个模块触发自己的初始化非常重要。

5 个答案:

答案 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才符合多线程。