我正在 Visual Studio 2013 中对使用旧静态链接库的旧应用程序 (CWinApp) 进行一些更改。我在应用程序中初始化常量字符串数组时遇到问题。
为了让事情变得更容易,我创建了一个基本示例来演示该问题。该示例由引用静态库 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
的成员初始化部分之前初始化此类常量字符串数组?
最佳答案
不是真的。不过,您也许可以解决您的具体情况。
ids
是动态初始化的全局变量。
您的全局 CTestApp
对象也是如此。
ids
在包含 header 的所有位置定义。 app
对象可能是在某个主文件中定义的。
C++ 未指定不同模块(.cpp 文件)中全局变量动态初始化的顺序。不同的编译、不同的编译器它可能有所不同。您不想依赖它。
如果需要保证顺序,唯一的办法就是将初始化放在同一个模块中。单个模块按照声明的顺序进行初始化。
因此,针对您的具体情况的解决方案是:在 header 中将 ids
声明为 extern
,并实际将其与您的全局 app
一起定义,就在之前。但是,这不会随着您获得更多类(class)而扩展。
或者,将 ids
更改为 const char*
数组,使其成为真正的常量。这将使其静态初始化,这发生在动态初始化之前。
最后,您可以将 mine
更改为(智能)指针,并仅在 InitInstance
中初始化它。
关于c++ - 如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21988793/