如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列
Posted
技术标签:
【中文标题】如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列【英文标题】:How to change Visual Studio C++ initialization sequence for const string arrays in statically linked libraries 【发布时间】:2014-02-24 13:10:47 【问题描述】:我正在对 Visual Studio 2013 中的旧应用程序 (CWinApp) 进行一些更改,该应用程序使用旧的静态链接库。我在应用程序中初始化 const 字符串数组时遇到问题。
为了让事情变得更简单,我创建了一个基本示例来演示该问题。该示例包含一个引用静态库 MyLib.lib 的 CWinApp 应用程序(类 CTestApp)。 CTestApp 拥有在 MyLib 中定义的 MyClass 类型的对象。以下是一些代码摘录:
主应用程序(CTestApp)
TestApp.h:
class CTestApp : public CWinApp
// --- Standard Wizard generated CWinApp stuff here ---
private:
MyClass mine;
;
TestApp.cpp:
// --- Standard Wizard generated CWinApp stuff here ---
CTestApp::CTestApp()
: mine(55)
静态库 (MyLib.lib)
MyClass.h:
#pragma once
#include <string>
const std::string ids[] =
"ABC",
"DEF",
"GHI"
;
const int num_ids = 3;
class MyClass
public:
MyClass(int id);
private:
int id;
std::string name;
;
MyClass.cpp:
#include "MyClass.h"
MyClass::MyClass(int id)
: id(id)
for (int i = 0; i < num_ids; ++i)
name += ids[i];
问题是当通过CTestApp::CTestApp
进入MyClass::MyClass
时,我发现数组ids
中的字符串是空的。同样奇怪的是,整数常量num_ids
被初始化为3
,正如预期的那样。这似乎只发生在静态库中声明的 const 字符串数组。如果我在CTestApp
本身中声明一个类似的数组,它会在我进入CTestApp::CTestApp
时被初始化。
我还发现,如果我运行应用程序并中断CTestApp::InitInstance
,则ids
已正确初始化。
有没有办法强制Visual Studio在进入CTestApp::CTestApp
的成员初始化部分之前初始化像这样的const字符串数组?
【问题讨论】:
【参考方案1】:不是真的。不过,您可能可以解决您的具体情况。
ids
是一个动态初始化的全局变量。
您的全局 CTestApp
对象也是如此。
ids
在包含标头的任何地方都被定义。 app
对象可能在某个主文件中定义。
C++ 未指定不同模块(.cpp 文件)中全局变量的动态初始化顺序。它可能因编译而异,因编译器而异。你不想依赖它。
如果需要保证顺序,唯一的办法就是把初始化放到同一个模块中。单个模块按声明顺序初始化。
因此,针对您的特定情况的解决方案是:在标题中将 ids
声明为 extern
,并在之前将其与全局 app
一起定义。但是,这并不会随着您获得更多课程而扩展。
或者,通过将ids
更改为const char*
的数组,使ids
成为真正的常量。这将使其静态初始化,这发生在动态初始化之前。
最后,您可以将mine
更改为(智能)指针,并仅在InitInstance
中对其进行初始化。
【讨论】:
这是对(有点)常见问题的解决方案的一个很好的总结。我通常会选择const char *
。
感谢 Sebastian,您提供了一些不错的选择。尽管为了简单起见,我在问题中使用了字符串数组,但我正在处理的遗留代码实际上包含一大堆 const 结构数组,每个数组初始化中都声明了常量字符串。我发现通过在结构定义中将string
更改为const char *
,我能够通过非常小的代码更改来解决问题。在这个阶段,我更改代码越少越好。以上是关于如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列的主要内容,如果未能解决你的问题,请参考以下文章
链接到静态库中的 explicit_bzero (glibc)