【问题标题】:force a global variable to be initialized before a certain static field强制全局变量在某个静态字段之前初始化
【发布时间】:2016-08-11 07:16:55
【问题描述】:

我希望在初始化静态字段 (#B) 之前调用全局变量的初始化 (#A)。

目前,一些静态字段在全局变量之前初始化。

GridUtil.h

class GridUtil{
   static Vec4* bPtr_;  //will be filled
   static void initGridCalculationCache();
   static class _init   //helper class
    {
        public:
        _init() { 
        static_iniAll(); 
        }
    } _initializer;

}

GridUtil.cpp

#include "GridUtil.h"
GridUtil::_init GridUtil::_initializer;// (Edit: This line is just added, thank Dietmar Kühl.)
Vec4 b[24];                      //#A executed 3rd : No, this should be the first.
Vec4* GridUtil::bPtr_=b;         //#B executed 1st
void GridUtil::initGridCalculationCache() {
    //.... fill GridUtil::bPtr_ using complex computation //#C executed 2nd
}

结果

从调试来看,上述代码的执行顺序是:-

B->C->A

但我想要:-

A->B->C

我注意到如果将“Vec4”替换为“int”,执行顺序将是:-

A->B->C

目标是使用静态函数 (initGridCalculationCache) 设置数组中元素的值 (bPtr_),该函数将自动调用(由类 _init 帮助)。

如果不可能,正确的方法是什么?

【问题讨论】:

  • 您是否尝试在包含 GridUtil.h 之前在 GridUtil.cpp 中声明全局变量,或者将其声明为静态?
  • 你可以看到全局信息:isocpp.org/wiki/faq/ctors#static-init-order.
  • @wasthishelpful 谢谢!这是正确的答案,如果您愿意,您可以发布为答案。
  • @javaLover 哪一个?移动位置还是使其静止?
  • wasthishelpful 的评论可以解决我的问题“在包含 GridUtil.h 之前在 GridUtil.cpp 中声明你的全局变量”; N0un - 感谢您提供出色的链接

标签: c++ arrays static global-variables


【解决方案1】:

按优先顺序排列的四个明显解决方案是:

  1. 不要从全局变量或static 成员变量开始!这些往往会产生大量问题,在使用并发的系统中更是如此。
  2. 使用constexpr 对象,因为它们在编译期间被初始化。显然,可以做什么有一些限制,但编译器会验证对象是否以正确的顺序初始化。
  3. 在翻译单元内,具有静态实时时间的对象从上到下初始化。也就是说,如果变量定义可以达到所需的顺序,则使用正确的顺序。但是,没有可移植的方法来跨翻译单元对变量初始化进行排序。
  4. 当来自不同翻译单元的对象之间存在初始化依赖关系时,可以使用返回引用的函数本地 static 对象来保证正确的顺序:这些将在首次访问时构建。

【讨论】:

  • "3. 在翻译单元内,具有静态生存时间的对象从上到下初始化。" OP的代码好像是一个TU中定义的对象没有从上到下初始化?
  • @songyuanyao 是的,OP 的代码没有初始化 A->B->C 。但是在我按照 wasthishelpful 的建议(移动#include)之后,它现在是正确的。我已经编辑了问题以使其清楚。 Dietmar Kühl 的描述与结果一致。
  • @javaLover 所以它并不总是从上到下,取决于其他一些事情(比如相关类定义的位置等)?我只是想确认一下。
  • @songyuanyao 我认为是从上到下,注意#include。我的错误代码在其他所有内容之前添加了#include,因此在 .cpp 角度来看, static_iniAll();在#A 之前调用。 ...... static_iniAll() 在 .h 中的“静态类 _init”行被调用......我认为它是每个 .cpp 的自上而下(不是 .h)
  • @javaLover:请注意,_initializer 在您发布的 sn-p 中没有定义。它在类定义中的存在只是一个声明而不是定义。除非它在某处定义,否则也不应该构造它!定义的位置将指定其在翻译单元中初始化的相对顺序。
【解决方案2】:

顺序相当简单,通过将它们从二进制文件的 .DATA 部分复制到 RAM 来初始化 POD。类在运行时由它们的 ctor 初始化。因此 POD 总是会在任何具有 ctor 的类之前被初始化,只要它们在同一个静态区域中。如果你使用 DLL/SO,一切都会变得有趣。

初始化顺序未定义。没有任何保证。如果您明确需要特殊顺序,请在 init 函数中初始化您的静态变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2013-07-21
    相关资源
    最近更新 更多