首页 > 解决方案 > C++ 从不引用静态类的静态成员。它会被确定初始化还是可以从二进制文件中省略?

问题描述

假设我有只有静态成员的 A 类。其成员之一是 B 类

class A { 
  //...
  static B b;
}

在 A.cpp 文件中,我使用它们的构造函数初始化所有静态成员。

A.cpp:

B A::b(/*constructor arguments*/);

现在,在我的整个项目中,我从未使用过变量 A::b。

这是否意味着编译器或链接器可以从最终的二进制文件中完全省略该变量的构造?

即使我从不使用该变量,它的构造也会对系统配置产生影响。(例如,它可能会影响外围寄存器)。

我没有使用makefile。我正在为 AVR uControllers 使用 Atmel 工作室。

如何确定该变量的构造函数将在我的程序的全局和静态初始化阶段执行?

而且,一般来说,我该如何控制呢?(可能有一种情况我需要相反的情况:确保它不会被初始化,除非某处需要)

我的印象是,如果在任何地方都没有对该名称的引用,则链接器可能会省略初始化代码。

真的吗?

如果使用文件 A.cpp 中的其他静态变量会有所不同吗?也许它与 IDE 自动创建 Makefile 有关,如果内部没有引用任何内容,它可能会省略整个 cpp 文件

*A.cpp 属于一个静态库,我将其作为 .a 文件包含在项目中

谢谢!

标签: c++

解决方案


It's a bit complicated, because it depends also on the linker.

If you are building static libraries lib*.a then it's possible that the object will not be pulled into an executable during linking. In this case it will not be run. see GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'

If you use shared libraries or just build an executable then the code will be in the binary. Now comes the question of will it be executed.

Whether a static storage duration object is initialized depends a tiny bit on the implementation (there is some leeway to allow for optimization). BUT I think most implementations usually do it before main(). But a static storage duration object must be initialized before any variable or function defined in the same translation unit are used. See 6.8.3.3 of the standard for exact legal definition. see https://stackoverflow.com/a/1273257/14065

Now there is also another thing you have to consider. All static storage duration objects in a translation unit are constructed in the same order that they are declared within the translation unit (that happen during the dynamic initialization phase). Note: the order across translation units is undefined. see https://stackoverflow.com/a/211307/14065

Note: There is also a "static initialization" phase that happens prior to "dynamic initialization" phase where all static storage duration objects are zero initialized or are initialized using constant expressions.

But because of "Initialization Order Fiasco" (hate that name, it's not a fiasco its well defined you just need to know the rules, but that's the name you should google). You should avoid static storage duration objects at file scope (especially if they reference other static storage variables at file scope).

But there is workaround: Create a static storage duration in a function and return a reference. Use the function to get access to the object and that will solve your initialization order issues.

Using functions rather than globals: Is access to a static function variable slower than access to a global variable?
Solving the order of initialization: https://stackoverflow.com/a/335746/14065


推荐阅读