C++:使用 int 与 struct 进行静态成员变量依赖初始化

2023-11-26

给定一个静态成员变量,它是从静态成员变量初始化的另一个班级,非字面意思struct ii有时默认初始化为0 or to 333。这取决于编译或链接顺序。伪代码展示:

class StaticClass: // file 'ONE.cpp/.hpp'
    static int i = 2
    static struct ii { int a = 333 }

class ABC: // file 'abc.cpp'
    static int abc_i = StaticClass::i   // always 2
    static struct abc_ii = StaticClass::ii // sometimes 0, sometimes 333

Calling g++ -std=c++11 abc.cpp ONE.cpp && ./a.out结果是i = 2 / ii = 0(gcc 4.8.1,与 clang++ 3.7 相同;-Wall -Wextra从不抱怨)。

但打电话g++ -std=c++11 ONE.cpp abc.cpp && ./a.out结果是i = 2 / ii = 333 !

同样的情况发生在ONE.o abc.o vs abc.o ONE.o以及以一种或另一种方式连接文件时:

cat ONE.cpp abc.cpp > X.cpp && g++ X.cpp && ./a.out vs cat abc.cpp ONE.cpp > Y.cpp && g++ Y.cpp && ./a.out

删除包含并在单个文件中移动代码,当存在以下顺序时,默认初始化为 0:

const OneI ABC::def_ii = StaticClass::ii; const OneI StaticClass::ii = OneI{333};

1 到 333 的顺序如下:

const OneI StaticClass::ii = OneI{333}; const OneI ABC::def_ii = StaticClass::ii;

为什么两个独立的编译单元会发生这种情况?是否可以通过始终强制执行后者的顺序来以某种方式避免这种情况?正在使用静态指针ABC to StaticClass::ii安全(不过我不想)?

完整的C++代码:


/* File: abc.cpp */

#include <iostream>
#include "ONE.hpp"

struct ABC {
  ABC();

  static const int def_i;
  static const OneI def_ii;
  void arg_i(const int &x) { std::cout << "i = " << x << " ";};
  void arg_ii(const OneI &x) { std::cout << "/ ii = " << x.a << " ";};

};

ABC::ABC() {
  arg_i(def_i);
  arg_ii(def_ii);
}

const int ABC::def_i = StaticClass::i;
const OneI ABC::def_ii = StaticClass::ii;

int main() {
  ABC a;
  std::cout << '\n';
}
/* End: abc.cpp */

/* File: ONE.cpp */

#include <iostream>

#include "ONE.hpp"

const int StaticClass::i = 2;
const OneI StaticClass::ii = OneI{333};

/* End: ONE.cpp */

/* File: ONE.hpp */

#include <iostream>

#ifndef One
#define One

struct OneI {
  OneI(int a_) : a(a_) { }
  int a;
};

struct StaticClass {
  const static int i;
  const static OneI ii;
};

#endif // One header guard

/* End: ONE.hpp */

恭喜!你遇到过静态初始化顺序惨败.

静态对象的初始化顺序未跨多个翻译单元定义。

StaticClass::ii is defined in ONE.cpp and ABC::def_ii is defined in abc.cpp. Therefore StaticClass::ii may or may not be initialized before ABC::def_ii. Since the initialization of ABC::def_ii uses the value of StaticClass::ii the value will depend on whether StaticClass::ii was initialized yet.

静态对象的初始化顺序within定义了一个翻译单元。对象按照定义的顺序进行初始化。因此,当您连接源文件时,初始化的顺序就被定义了。但是,当您以错误的顺序连接文件时,定义的初始化顺序是错误的:

const OneI ABC::def_ii = StaticClass::ii; // StaticClass::ii wasn't initialized yet
const OneI StaticClass::ii = OneI{333};

是否可以通过始终强制执行后者的顺序来以某种方式避免这种情况?

最简单的解决方案是在同一个翻译单元中以正确的顺序定义两个对象。更通用的解决方案是使用初始化静态对象首次使用习语时构建.

正在使用静态指针ABC to StaticClass::ii安全(不过我不想)?

只要在定义指向对象的另一个翻译单元中的静态对象初始化期间不使用指针的解引用值,是的,替换ABC::def_ii用指针就安全了。


StaticClass::ii will have been zero-initialized during the static initialization phase††. The Static initialization order fiasco concerns the dynamic initialization phase††.

†† C++ standard draft [basic.start.static]

如果不执行常量初始化,则具有静态存储持续时间([basic.stc.static])或线程存储持续时间([basic.stc.thread])的变量将被零初始化([dcl.init])。零初始化和常量初始化一起称为静态初始化;所有其他初始化都是动态初始化。静态初始化应在任何动态初始化发生之前执行。 [注:非局部变量的动态初始化在[basic.start.dynamic]中描述;局部静态变量的描述在[stmt.dcl]中。 ——尾注]

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++:使用 int 与 struct 进行静态成员变量依赖初始化 的相关文章

  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • iphone sqlite 静态链接?

    有人静态链接 sqlite 而不是使用动态链接 吗 我遇到的问题是 越狱手机的用户没有与普通 iPhone 所采用的 sqlite 版本相同的版本 因此导致崩溃 我假设在我的应用程序中静态链接已知版本的 sqlite 就是答案 我需要全文支
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 设置在 matplotlib 中使用 plt.subplots 创建的图形的高度和宽度?

    在 matplotlib 中 我知道如何设置图形的高度 宽度和 DPI fig plt figure figsize 4 5 dpi 100 然而 似乎如果我想创建小的多个图 我无法创建这样的图形 我必须使用这个 fig subplots
  • ASP.NET MVC - 使用 ViewData 将 Json 字符串传递给视图

    我正在尝试使用 ViewData 将 Json 传递到我的视图 控制器 ViewData JsonRegionList Json RegionService GetActiveRegions view input UserRegion au
  • 非中心卡方概率和非中心参数

    如何获得非中心参数的值 对于不同的临界值和自由度 该参数的概率恰好为 0 9 例如 显着性水平 0 05 且自由度为 1 临界值 3 84 时 ncp 必须等于 10 50742 才能获得 0 9 的概率 1 pchisq 3 841459
  • Android 深度链接与自定义 URI

    我在清单中定义了以下内容
  • “PHP 通知:未定义的属性”[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 我收到这个奇怪的错误 你会说 为什么奇怪 你只是没有这
  • 运行一个进程并退出而不等待它

    在 Windows 下的 Python 中 我想在单独的进程中运行一些代码 我不希望家长等待它结束 尝试过这个 from multiprocessing import Process from time import sleep def c
  • C# 中委托不可变的目的是什么?

    我正在看一本图解C 2012的Combining Delegates一节 没有注意到这一点吗 代表们的目的是一成不变的 合并代表 到目前为止 您见过的所有代表都只有 其调用列表中的单个方法 代表可以 合并 通过使用加法运算符 运算的结果是
  • Redis集群与Spring boot集成

    我有一个具有主服务器 从服务器和 3 个哨兵服务器的 Redis 集群 主服务器和从服务器映射到 dns 名称为 node1 redis dev com node2 redis dev com redis服务器版本是2 8 我将以下内容包含
  • 找出Windows服务正在运行的进程名称.NET 1.1

    我们正在使用一个写得不好的 Windows 服务 当我们试图从代码中停止它时 它会挂起 因此 我们需要找到与该服务相关的进程并将其杀死 有什么建议么 您可以使用System Management MangementObjectSearche
  • “每个表只能有一个 IDENTITY 列” - 为什么?

    每个表只能有一个 IDENTITY 列 为什么会这样呢 以车辆为例 存在唯一的底盘号以及唯一的车牌号 为了描述这个场景sql服务器我们需要对其中一个列进行自定义实现 相反 在Oracle一张桌子上可以有任意数量的序列 为什么对 IDENTI
  • 如何在html动作链接中插入图像? ASP.NET MVC

    我的 web 项目上有来自 html 操作链接的导航和许多链接 它们很丑 有下划线 我想插入一些带有名称的图像或使用操作链接的样式 是否可以 怎么做 谢谢并保重 拉吉姆斯 您可以使用 css 删除下划线或放置背景图片 否则你也可以像这样创建
  • 来自元组的构造函数参数

    如果我有一个像这样的结构 struct Thing int x int y bool a bool b 然后我可以创建一个Thing对象通过这样做 Thing t 1 2 true false 但是 如果我有一个元组 那么我会做类似的事情
  • 如何在 Angular 2 中使用 SheetJS (js-xlsx)

    我正在学习 angular2 我想使用js xlsx我的项目中的库 我安装了xlsxnpm install xlsx和jszipnpm install jszip并将它们添加到我的index html中 并添加了打字稿定义tsd insta
  • 用于重载传递的函数指针类型的表达式 SFINAE

    在此示例中 函数被传递给隐式实例化的函数模板 Function that will be passed as argument int foo return 0 Function template to call passed functi
  • Karma jasmine 测试:在终端中突出显示差异

    我使用 Karma 和 Jasmine 进行测试 在某些测试中 我有测试所依赖的大型对象 当我做类似的事情时 expect obj toEqual expectedObj and obj expectedObj 我在终端中收到一条错误消息
  • 如何从 PowerPoint 调色板获取 RGB/Long 值

    我正在尝试 大部分成功 从活动中 读取 颜色ThemeColorScheme 下面的子例程将从主题中获取 12 种颜色 例如这是myAccent1 我还需要从调色板中获取另外 4 种颜色 我需要的四种颜色是上面指示的颜色正下方的一种 然后是
  • ASP.NET 自动注销

    我正在和另外 4 个人一起做一个小组项目 我们正在使用嵌入式 C 在 MVC4 中的 ASP NET 中设计一个工作亭 我正在努力让系统在用户闲置 10 分钟时将其注销 我需要一些关于如何开始编写系统注销用户的方法的帮助 如果您不使用 Wi
  • 在 ArrayList 中的单个索引处添加多个值

    我有一个双ArrayList在java中是这样的 List
  • 异常 java.lang.SecurityException:读取 ..MediaDocumentsProvider ... 需要 android.permission.MANAGE_DOCUMENTS 或 grantUriPermission()

    当我尝试为个人资料图片选择图片时 我仅在某些设备中发现此问题 在检查模拟器时 看不到这些问题 但在应用程序的实时版本上 该用户面临着这个问题 从 firebase 崩溃报告中捕获的屏幕截图 请帮我解决这个问题 AndroidManifest
  • C++:使用 int 与 struct 进行静态成员变量依赖初始化

    给定一个静态成员变量 它是从静态成员变量初始化的另一个班级 非字面意思struct ii有时默认初始化为0 or to 333 这取决于编译或链接顺序 伪代码展示 class StaticClass file ONE cpp hpp sta