为什么静态数据成员可能无法初始化?

2024-01-06

我试图在加载时向工厂注册一堆类。我的策略是利用静态初始化来确保在 main() 开始之前,工厂已准备就绪。当我动态链接库时,此策略似乎有效,但当我静态链接时则无效;当我静态链接时,只有一些静态数据成员被初始化。

假设我的工厂生产汽车。我有 CarCreator 类,可以实例化少数汽车,但不是全部。我希望工厂收集所有这些 CarCreator 类,以便寻找新车的代码可以进入工厂,而不必知道谁将进行实际的构建。

所以我有

CarTypes.hpp

enum CarTypes
{
   prius = 0,
   miata,
   hooptie,
   n_car_types
};

我的工厂.hpp

class CarCreator
{
public:
   virtual Car * create_a_car( CarType ) = 0;
   virtual std::list< CarTypes > list_cars_I_create() = 0;
};

class MyFactory // makes cars
{
public:
   Car * create_car( CarType type );
   void factory_register( CarCreator * )

   static MyFactory * get_instance(); // singleton
private:
   MyFactory();

   std::vector< CarCreator * > car_creator_map;
};

我的工厂.cpp

MyFactory:: MyFactory() : car_creator_map( n_car_types );

MyFactory * MyFactory::get_instance() {
   static MyFactory * instance( 0 ); /// Safe singleton
   if ( instance == 0 ) {
      instance = new MyFactory;
   }
   return instance;
}

void MyFactory::factory_register( CarCreator * creator )
{
   std::list< CarTypes > types = creator->list_cars_I_create();
   for ( std::list< CarTypes >::const_iteator iter = types.begin();
         iter != types.end(); ++iter ) {
      car_creator_map[ *iter ] = creator;
   }
}

Car * MyFactory::create_car( CarType type ) 
{
   if ( car_creator_map[ type ] == 0 ) { // SERIOUS ERROR!
      exit();
   }
   return car_creator_map[ type ]->create_a_car( type );
}

...

然后我将拥有特定的汽车和特定的汽车创造者:

米亚塔.cpp

class Miata : public Car {...};

class MiataCreator : public CarCreator {
public:
   virtual Car * create_a_car( CarType );
   virtual std::list< CarTypes > list_cars_I_create();
private:
   static bool register_with_factory();
   static bool registered;
};

bool MiataCreator::register_with_factory()
{
   MyFactory::get_instance()->factory_register( new MiataCreator );
   return true;
}

bool MiataCreator::registered( MiataCreator::register_with_factory() );

...

重申一下:动态链接我的库,MiataCreator::registered 将被初始化,静态链接我的库,它不会被初始化。

通过静态构建,当有人去工厂请求 Miata 时,car_creator_map将指向 NULL 并且程序将退出。

私有静态整型数据成员是否有什么特殊之处,它们的初始化将以某种方式被跳过?静态数据成员是否仅在使用类时才初始化?我的 CarCreator 类未在任何头文件中声明;它们完全位于 .cpp 文件中。编译器是否有可能内联初始化函数并以某种方式避免调用 MyFactory::factory_register?

有没有更好的办法解决这个注册问题?

在单个函数中列出所有 CarCreators、向工厂显式注册每个 CarCreators、然后保证调用该函数并不是一种选择。特别是,我想将几​​个库链接在一起并在这些单独的库中定义 CarCreators,但仍然使用单个工厂来构建它们。

...

以下是我期待的一些答复,但它们并不能解决我的问题:

1)你的单例工厂不是线程安全的。 a)没关系,我只使用一个线程。

2) 当你的 CarCreators 初始化时,你的单例工厂可能未初始化(即你遇到了静态初始化失败) a)我通过将单例实例放入函数中来使用单例类的安全版本。如果这是一个问题,如果我向MiataCreator's::register_with_factory方法:我没有。


我认为你有一个静态初始化顺序惨败,但不是与工厂。

这并不是说注册标志没有被初始化,而是没有足够快地初始化。

您不能依赖静态初始化顺序,除非:

  1. 在同一翻译单元(.cpp 文件)中定义的静态变量将按照列出的顺序进行初始化
  2. 翻译单元中定义的静态变量将在第一次调用该翻译单元中的任何函数或方法之前进行初始化。

你什么cannot依赖的是静态变量将在函数或方法之前初始化其他第一次调用翻译单元。

特别是,在首次调用 MyFactory::create_car(在 MyFactory.cpp 中定义)之前,您不能依赖 MiataCreator::registered(在 Miata.cpp 中定义)进行初始化。

像所有未定义的行为一样,有时您会得到您想要的东西,有时您不会,并且最奇怪、最看似无关的事情(例如静态链接与动态链接)可以改变它是否按照您想要的方式工作。

您需要做的是为 Miata.cpp 中定义的注册标志创建静态访问器方法,并让 MyFactory 工厂通过此访问器获取值。由于访问器与变量定义位于同一翻译单元中,因此变量将在访问器运行时初始化。然后您需要从某个地方调用此访问器。

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

为什么静态数据成员可能无法初始化? 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐

  • 如何找到使用 gdb 定义的文件?

    当我打字时list mystruct进入 gdb 我收到用于定义 mystruct 的代码行 我怎样才能要求 gdb 给我它正在读取的文件来打印这些行 从 gdb python 接口获取该文件会更好 越容易解析越好 Thanks 为了显示类
  • 从输入中获取整数值并动态生成输入

    我想在焦点从 移开 时动态获取输入End Date 输入并传递天数到 JQuery 并生成它 我尝试了这段代码但不起作用 从几天中获取价值并生成面板数量 就是这样
  • C#:寻求快速数据结构以将像素添加到分区 HSB 直方图

    在我的应用程序中 我使用快速非托管代码从多个图像读取 RGB 像素值 然后将它们转换为 HSB 颜色 现在我想使用以下分区构建 HSB 直方图 色调 18 个分区 从 0 360 产生 20 个间隔 饱和度 3 个分区 从 0 1 产生 0
  • NHibernate 查询建模

    通常我会将我的 criterias hql 查询放在与实体相关的存储库 dal 类中 但最近我一直在考虑添加另一个表示查询是什么的抽象 这将使我有可能将常见行为添加到基类中的所有查询 例如分页 等 现在这些就是我的组件 与 nhiberna
  • 在常规发布请求中设置标头

    我需要设置一个header in a post请求 授权 request token 我尝试过使用 wslite 和 groovyx net http HTTPBuilder 但我总是得到 401 未授权 这意味着我无法正确设置标头 我也想
  • 在 terraform 中构建输出地图

    我有一个要创建的用户列表 一个 sns 主题列表以及创建策略以向用户授予主题权限 这些都是针对用户的命名空间 Given main tf provider aws region eu west 1 profile terraform mod
  • 将调用命令的输出封装在变量中 - PowerShell

    我有一个在远程计算机 来自 DC 上安装远程桌面服务的脚本 我现在正处于检查 RDS 是否安装在连接代理 服务器 和连接主机 服务器 上的阶段 我想使用调用命令 因为远程 powershell 会话似乎太复杂了 这是我的代码 res Inv
  • 在 Windows 中使用子进程运行 python 脚本。来自 emacswiki 的 Python 代码检查器包装器产生相同的错误

    所以我正在尝试设置 emacs wiki 中建议的 python 代码检查器 但是 我无法在命令 shell 中运行这些脚本 更不用说 emacs 了 该部分可在此处找到 http www emacswiki org emacs Pytho
  • 将字符串存储到c中的数组中

    据我所知 我可以创建一个包含项目的数组 例如 char test1 3 arrtest ao 123 但是我如何将我的输入存储到上面的代码之类的数组中 因为我只能将其编码为 input 10 scanf s input or gets in
  • 在运行时更改 iOS 模拟器的当前区域设置

    在开发一组用于将数值和日期转换为字符串的日期计算和语言规则时 我正在编写断言字符串格式化方法的结果的测试 一个虚构的断言可能如下所示 NSAssert dateString isEqualToString Three days until
  • Python-撤消标准输出重定向

    所以我知道从 在Python中将标准输出重定向到 无 https stackoverflow com questions 6735917 redirecting stdout to nothing in python 您可以抑制 print
  • os.kill 没有引发 OSError,但是我没有看到给定的 pid 正在运行

    在我的 ubuntu 服务器上运行以下命令 python c import os os kill 5555 0 这样做是为了查看 pid 5555 是否正在运行 根据我的理解 如果 pid 没有运行 这应该会引发 OSError 这不会对我
  • 已存在记录检查的逻辑,但仅在更新表单值的情况下[重复]

    这个问题在这里已经有答案了 我正在开发一个名为县经理的模块 我在检查县 mysql 表中已存在的县及其国家 地区时遇到问题 Database table 让我解释 Add Page In add page i am having 2 fie
  • [String] 与 [(String)] 有什么区别?

    Swift 中 String 和 String 有什么区别 我让他们使用let arr1 String and let arr2 String 应该没有什么区别 如果你看到的话 这是 Xcode 或 Swift 中的一个小故障 String
  • 如何使用 std::copy 将一张地图复制到另一张地图?

    我想将一个 std map 的内容复制到另一个 std map 中 我可以用吗std copy为了那个原因 显然 下面的代码是行不通的 int main typedef std map
  • 跟踪对 Delphi 中的文件夹所做的更改

    我需要编写一个 Delphi 程序来监视文件夹的更改 添加 更新 重命名和删除文件 我看到了使用 TShellChangeNotifier 的建议 这是这个问题的正确解决方案吗 我应该如何使用它 This question https st
  • 从 SQL Server 检索数据并将其转换为 json 格式?

    我正在使用 PHP 5 6 0 并连接到我的本地 SQL Server 我能够检索数据 但它是数组格式 我想把它转换成json格式 我得到什么 date gt 2013 02 05 16 02 02 000000 timezone type
  • C++ 将字符串转换为十六进制,反之亦然

    在 C 中将字符串转换为十六进制或反之亦然的最佳方法是什么 Example 像这样的字符串 Hello World 转为十六进制格式 48656C6C6F20576F726C64 并从十六进制48656C6C6F20576F726C64字符
  • 尝试跟踪 Firefox 中未完成的 AJAX 请求的数量

    我正在使用 Selenium 来测试 Web 应用程序 并且不允许修改应用程序的 javascript 代码 我试图通过使用 GreaseMonkey 覆盖 XMLHttpRequest send 来跟踪未完成的 AJAX 请求的数量 新的
  • 为什么静态数据成员可能无法初始化?

    我试图在加载时向工厂注册一堆类 我的策略是利用静态初始化来确保在 main 开始之前 工厂已准备就绪 当我动态链接库时 此策略似乎有效 但当我静态链接时则无效 当我静态链接时 只有一些静态数据成员被初始化 假设我的工厂生产汽车 我有 Car