C++ 如何更改Visual Studio C++;静态链接库中常量字符串数组的初始化序列

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

我正在Visual Studio 2013中对传统应用程序(CWinApp)进行一些更改,该应用程序使用传统的静态链接库。我在应用程序中初始化常量字符串数组时遇到问题

为了让事情变得更简单,我创建了一个基本示例来演示这个问题。该示例由一个CWinApp应用程序(类CTestApp)组成,该应用程序引用静态库MyLib.lib。CTestApp拥有MyLib中定义的MyClass类型的对象。以下是一些代码摘录:

主要应用程序(CTestApp) TestApp.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];
   }
}
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*
,我可以通过非常小的代码更改来解决这个问题。在这个阶段,我对代码的修改越少越好。