Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 部分初始化其他模块中定义的变量_C++_Optimization_Compiler Construction_Static_Initialization - Fatal编程技术网

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

C++ 部分初始化其他模块中定义的变量,c++,optimization,compiler-construction,static,initialization,C++,Optimization,Compiler Construction,Static,Initialization,我正在考虑一个特定的解决方案,其中我想初始化在其他模块中定义的数组的一个单元(将有许多模块初始化一个表)。在运行main之前不会读取数组(因此静态初始化顺序没有问题) 我的做法: /* secondary module */ extern int i[10]; // the array const struct Initialize { Initialize() { i[0] = 12345; } } init; /*主模块*/ #包括 int i[10]; int main(

我正在考虑一个特定的解决方案,其中我想初始化在其他模块中定义的数组的一个单元(将有许多模块初始化一个表)。在运行main之前不会读取数组(因此静态初始化顺序没有问题)

我的做法:

/* secondary module */

 extern int i[10]; // the array

 const struct Initialize {
  Initialize() { i[0] = 12345; }
 } init;

/*主模块*/
#包括
int i[10];
int main()
{
printf(“%d\n”,i[0]);//检查该值是否已初始化
}
编译器不会去掉
init
常量,因为构造函数有副作用。我说得对吗?机械装置可以吗?在GCC(-O3)上,一切正常

//编辑
在现实世界中,将有许多模块我希望避免额外的模块,这是一个集中所有次要初始化例程的中心位置(为了更好的可扩展性)。因此,每个模块触发自己的初始化非常重要。

编辑

 /*secondary module (secondary.cpp) */

  int i[10]; 
  void func()
  {
       i[0]=1;

  }

/*主模块(main.cpp)*/
#包括
外部内部i[];
void func();
int main()
{
func();

std::cout我认为您不希望在主模块adf88中使用
extern int I[10];

这可能会起作用,但很危险。单个模块中的全局/静态构造顺序是未定义的,模块加载顺序也是未定义的(除非您明确管理它)。例如,您假设在secondary.c Initialize()ctor运行期间,i已经存在。您必须非常小心,不要让两个模块初始化相同的公共数据,或者让两个模块执行初始化时产生重叠的副作用

我认为解决这种需求的更简洁的设计是让公共数据的所有者(您的主模块)将其作为全局单例公开,并提供一个接口来执行所需的任何数据初始化。您将有一个中心位置来控制初始化顺序,甚至可能控制并发访问(使用关键部分或其他并发原语)-

/主模块(main.c)/

#包括 公共类 { 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++)。

< P>这是用MSVC编译器进行的,但是GNU C++不适用(至少对我来说)。GNU链接器会删除所有未在编译单元外使用的符号。我知道只有一种方法可以保证初始化:“init一”。成语。例如:

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);

我可以问一下,当您可以使用
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
}

这似乎更简单,也不容易出错。但在C++0x之前,它是不兼容多线程的。

有一点很重要-您没有注意到我想要初始化表的单元格。我编辑了我的示例,以便它现在在代码中可见。我也编辑了我的帖子-我更好地解释了写“在模块内初始化”时我想说的话。您仍然假设在每个模块初始化期间,i[]阵列已经分配(未初始化)。当应用程序启动时,AFAIK静态存储空间在一个步骤中分配(并归零)。启动:这是关于全局静态存储空间什么是“模块”?转换单元?共享库?静态库?如我所写“在运行main之前不会读取数组"因此,初始化顺序没有问题。我不希望在中心位置进行初始化。我希望每个次要初始化都从关联的模块触发。这不仅仅是初始化顺序问题-您能否保证在辅助模块初始化期间甚至分配阵列?在单个翻译单元根据3.6.2定义得很好。我不确定您称之为“模块”的是什么——因此,这可能只是对它在更精细粒度级别上的表现的评论(假设为“模块”>translation unit)我将OP中的“module”解释为二进制,比如windows中的dll。是否定义了依赖dll加载的顺序?这实际上是一个诚实的问题-可能存在这样一个我不知道的规范。哦,我看到OP评论说他指的是翻译单元。因此init顺序的关注点确实是不相关的。接受。那么我尝试做的是不可能。必须从单元外部以某种方式引用初始值设定项。如果没有这种风险,则意味着您的模块已经紧密耦合(即他们需要知道写入哪个索引)在这种情况下,你最好把它写在一个源文件中,这样你就可以一目了然地检查索引是否正确。我的观点是关于解耦的。
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);
#include "init_once.h"

class Init : public InitOnce<Init>
{
public:
    Init();
    ~Init();
};
static Init module_init_;
 #include "unit.h"
 extern int i[10]; // the array

 Init::Init()
 {
     i[0] = 12345;
 }
 ...
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);