C++ 如何更改Visual Studio C++;静态链接库中常量字符串数组的初始化序列
我正在Visual Studio 2013中对传统应用程序(CWinApp)进行一些更改,该应用程序使用传统的静态链接库。我在应用程序中初始化常量字符串数组时遇到问题 为了让事情变得更简单,我创建了一个基本示例来演示这个问题。该示例由一个CWinApp应用程序(类CTestApp)组成,该应用程序引用静态库MyLib.lib。CTestApp拥有MyLib中定义的MyClass类型的对象。以下是一些代码摘录: 主要应用程序(CTestApp) TestApp.h:C++ 如何更改Visual Studio C++;静态链接库中常量字符串数组的初始化序列,c++,visual-studio,visual-c++,visual-studio-2013,C++,Visual Studio,Visual C++,Visual Studio 2013,我正在Visual Studio 2013中对传统应用程序(CWinApp)进行一些更改,该应用程序使用传统的静态链接库。我在应用程序中初始化常量字符串数组时遇到问题 为了让事情变得更简单,我创建了一个基本示例来演示这个问题。该示例由一个CWinApp应用程序(类CTestApp)组成,该应用程序引用静态库MyLib.lib。CTestApp拥有MyLib中定义的MyClass类型的对象。以下是一些代码摘录: 主要应用程序(CTestApp) TestApp.h: class CTestApp
class CTestApp : public CWinApp
{
// --- Standard Wizard generated CWinApp stuff here ---
private:
MyClass mine;
};
// --- Standard Wizard generated CWinApp stuff here ---
CTestApp::CTestApp()
: mine(55)
{
}
#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;
};
#include "MyClass.h"
MyClass::MyClass(int id)
: id(id)
{
for (int i = 0; i < num_ids; ++i)
{
name += ids[i];
}
}
TestApp.cpp:
class CTestApp : public CWinApp
{
// --- Standard Wizard generated CWinApp stuff here ---
private:
MyClass mine;
};
// --- Standard Wizard generated CWinApp stuff here ---
CTestApp::CTestApp()
: mine(55)
{
}
#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;
};
#include "MyClass.h"
MyClass::MyClass(int id)
: id(id)
{
for (int i = 0; i < num_ids; ++i)
{
name += ids[i];
}
}
静态库(MyLib.lib)
MyClass.h:
class CTestApp : public CWinApp
{
// --- Standard Wizard generated CWinApp stuff here ---
private:
MyClass mine;
};
// --- Standard Wizard generated CWinApp stuff here ---
CTestApp::CTestApp()
: mine(55)
{
}
#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;
};
#include "MyClass.h"
MyClass::MyClass(int id)
: id(id)
{
for (int i = 0; i < num_ids; ++i)
{
name += ids[i];
}
}
#pragma一次
#包括
常量std::字符串ID[]=
{
“ABC”,
“DEF”,
“GHI”
};
常量int num_id=3;
类MyClass
{
公众:
MyClass(int-id);
私人:
int-id;
std::字符串名;
};
MyClass.cpp:
class CTestApp : public CWinApp
{
// --- Standard Wizard generated CWinApp stuff here ---
private:
MyClass mine;
};
// --- Standard Wizard generated CWinApp stuff here ---
CTestApp::CTestApp()
: mine(55)
{
}
#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;
};
#include "MyClass.h"
MyClass::MyClass(int id)
: id(id)
{
for (int i = 0; i < num_ids; ++i)
{
name += ids[i];
}
}
#包括“MyClass.h”
MyClass::MyClass(int id)
:id(id)
{
对于(int i=0;i
问题是,当通过CTestApp::CTestApp
进入MyClass::MyClass
时,我发现数组ids
中的字符串是空的。同样奇怪的是,整数常量num_id
按预期初始化为3
。这似乎只发生在静态库中声明的常量字符串数组中。如果我在CTestApp
本身中声明了一个类似的数组,那么当我进入CTestApp::CTestApp
时,它将被初始化
我还发现,如果运行应用程序并插入CTestApp::InitInstance
,则ids
已正确初始化
在进入
CTestApp::CTestApp
的成员初始化部分之前,是否有一种方法可以强制Visual Studio初始化常量字符串数组,例如这样的数组。不过,您可能可以解决您的具体案例
ids
是一个具有动态初始化的全局变量
您的全局CTestApp
对象也是如此
ids
在包含标头的所有位置都定义。app
对象可能是在某个主文件中定义的
<>不同模块(CpP文件)中全局变量的动态初始化顺序由C++指定。不同的编译,不同的编译器,它可能有所不同。你不想依赖它
如果您需要保证订单,唯一的方法是将初始化放在同一个模块中。单个模块按声明顺序初始化
因此,针对您的具体情况的解决方案是:在标题中将ids
声明为extern
,并在前面将其与您的全局应用程序一起实际定义。然而,这并不会随着你得到更多的类而扩展
或者,将ids
更改为const char*
数组,使其成为真常量。这将使它静态初始化,这发生在动态初始化之前
最后,您可以将mine
更改为(智能)指针,并仅在InitInstance
中初始化它。不过,您可能可以解决您的具体案例
ids
是一个具有动态初始化的全局变量
您的全局CTestApp
对象也是如此
ids
在包含标头的所有位置都定义。app
对象可能是在某个主文件中定义的
<>不同模块(CpP文件)中全局变量的动态初始化顺序由C++指定。不同的编译,不同的编译器,它可能有所不同。你不想依赖它
如果您需要保证订单,唯一的方法是将初始化放在同一个模块中。单个模块按声明顺序初始化
因此,针对您的具体情况的解决方案是:在标题中将ids
声明为extern
,并在前面将其与您的全局应用程序一起实际定义。然而,这并不会随着你得到更多的类而扩展
或者,将ids
更改为const char*
数组,使其成为真常量。这将使它静态初始化,这发生在动态初始化之前
最后,您可以将mine
更改为(智能)指针,并仅在InitInstance
中对其进行初始化,这是(某种程度上)常见问题的一系列解决方案。我通常选择常量字符*
。谢谢塞巴斯蒂安,你给了我一些不错的选择。虽然为了简单起见,我在问题中使用了一个字符串数组,但我正在处理的遗留代码实际上包含了一大堆结构的常量数组,每个数组初始化中都声明了常量字符串。我发现,通过将结构定义中的string
更改为const char*
,我可以通过非常小的代码更改来解决这个问题。在这个阶段,我对代码的修改越少越好。这是一个(有些)常见问题的很好的解决方案。我通常选择常量字符*
。谢谢塞巴斯蒂安,你给了我一些不错的选择。虽然为了简单起见,我在问题中使用了一个字符串数组,但我正在处理的遗留代码实际上包含了一大堆结构的常量数组,每个数组初始化中都声明了常量字符串。我发现,通过将结构定义中的string
更改为const char*
,我可以通过非常小的代码更改来解决这个问题。在这个阶段,我对代码的修改越少越好。