C++ 大型动态多维数组不工作

C++ 大型动态多维数组不工作,c++,arrays,dynamic,multidimensional-array,C++,Arrays,Dynamic,Multidimensional Array,我的代码非常大而且复杂,所以我不会浪费你的时间去阅读它,但是你必须对其中的变量做出一些假设。我将告诉您我在调试器中确认的变量值,以便您可以确定地知道。要知道,我在这里省略了很多不相关的代码,所以您看到的并不是全部,但我已经包含了所有相关的内容 // This is defined in a class: char**** m_DataKeys; // This is in a member function of the same class: m_DataKeys = new char**

我的代码非常大而且复杂,所以我不会浪费你的时间去阅读它,但是你必须对其中的变量做出一些假设。我将告诉您我在调试器中确认的变量值,以便您可以确定地知道。要知道,我在这里省略了很多不相关的代码,所以您看到的并不是全部,但我已经包含了所有相关的内容

// This is defined in a class:
char**** m_DataKeys;


// This is in a member function of the same class:
m_DataKeys = new char*** [m_iNumOfHeroes];  // m_iNumOfHeroes = 2

while ( pkvHero )
{
  // iHeroNum = 0 and then 1      #define NUM_OF_ABILITIES 4
  m_DataKeys[iHeroNum] = new char** [NUM_OF_ABILITIES];

  for (int ability = 0; ability < NUM_OF_ABILITIES; ability++)
  {
    if (pkvExtraData)  // only is true when iHeroNum == 1 and ability == 0
    {
      // iNumOfExtraData == 2
      m_DataKeys[iHeroNum][ability] = new char* [iNumOfExtraData];

      while ( pkvSubKey )
      {
        // iCurExtraDataNum increments from 0 to 2
        m_DataKeys[iHeroNum][ability][iCurExtraDataNum] = new char [50];
在调用该行之前,当iHeroNum==0时,m_数据键数组如下所示:

m_DataKeys | 0x02072a60
  pointer | 0xffeeffee
    Error : expression cannot be evaluated
m_DataKeys | 0x02072a60
  pointer | 0x02496b00
    pointer | 0xffeeffee
      Error : expression cannot be evaluated
这是意料之中的。调用该行后,它看起来像:

m_DataKeys | 0x02072a60
  pointer | 0xffeeffee
    Error : expression cannot be evaluated
m_DataKeys | 0x02072a60
  pointer | 0x02496b00
    pointer | 0xffeeffee
      Error : expression cannot be evaluated
看起来是对的。但是,因为我在那里设置了一个断点,所以我点击play并让它在下一个循环中点击它,此时iHeroNum==1并运行该行,然后m_数据键如下所示:

m_DataKeys | 0x02072a60
  pointer | 0x02496b00
    pointer | 0xffeeffee
      Error : expression cannot be evaluated
这和以前完全一样!该行没有更改数组。。。。一点也不

为了澄清,m_DataKeys是指向大小为50的字符数组的三维字符指针数组

我不明白为什么会发生这种情况,看起来我的代码是正确的。有没有可能垃圾回收员在这里骗我?或者新的分配器

编辑:更大问题的症状 让我详细说明一下我的代码结构,因为实际上,这只是一个更大问题的廉价解决方案

我已经有了你们其中一位明智建议的结构:

struct HeroData
{
  // Lots o data here
  // ...
  // .
  //
  AbilityData* Abilities[NUM_OF_ABILITIES];
}

struct AbilityData
{
  // More data here
  // ...
  // .
  CUtlMap<char*,int> ExtraData [MAX_ABILITY_LEVELS];
}
struct-HeroData
{
//这里有很多数据
// ...
// .
//
能力数据*能力[能力数量];
}
结构能力数据
{
//这里有更多数据
// ...
// .
CUtlMap ExtraData[最大能力水平];
}
现在,当它变得复杂,我不得不这样做时,DataKeys指针数组指向指针数组垃圾只是在需要将一些数据加载到一个动态结构时,其中键、值和数据数量都是完全动态的。所以我想使用字符数组到int的映射,但唯一的问题是我不能在映射中存储实际的字符数组,我必须使用char*。我尝试将地图定义为:

CUtlMap<char[50],int> ExtraData [MAX_ABILITY_LEVELS];
CUtlMap ExtraData[最大能力水平];

但这真的不起作用,而且对我来说似乎有点奇怪。所以,我必须找到一个地方来粘贴所有这些ExtraDataKey,出于某种原因,我认为这样做很酷。如何将字符数组存储在数组或映射之类的对象中?

既然您使用指针作为类成员,我最好的猜测是您违反了。也就是说,您没有为类提供复制构造函数和复制赋值运算符。在传递类的对象时,这通常会导致奇怪的数据丢失

注意,没有健全的C++程序员会使用<代码> char ***/COD>。下面是我使用向量和字符串修复问题的最佳尝试,但对于您的特定问题,可能有更好的设计:

#include <string>
#include <vector>

class Foo
{
    int m_iNumOfHeroes;
    std::vector<std::vector<std::vector<std::string> > > m_DataKeys;

    enum { NUM_OF_ABILITIES = 4, iNumOfExtraData = 2 };

public:

    explicit Foo(int iNumOfHeroes)
    : m_iNumOfHeroes(iNumOfHeroes)
    , m_DataKeys(m_iNumOfHeroes, std::vector<std::vector<std::string> >
                 (NUM_OF_ABILITIES, std::vector<std::string>(iNumOfExtraData)))
    {
    }
};

int main()
{
    Foo x(2);
}
#包括
#包括
福班
{
国际摩纳哥英雄;
std::向量m_数据键;
枚举{NUM_OF_能力=4,iNumOfExtraData=2};
公众:
显式Foo(int)
:m_inumofheromes(inumofheromes)
,m_数据键(m_,std::vector
(能力的数量,std::vector(iNumOfExtraData)))
{
}
};
int main()
{
foox(2);
}
如果您以前从未在构造函数中看到过冒号语法,那么这就是一个

<>我真的希望C++有数组边界检查< /p>
如果使用
foo.at(i)
语法而不是
foo[i]
,那么
std::vector
std::string
确实有边界检查。在调试模式下,即使 Fo[i] < /C>在VisualC++、Irc.

< P>中启用了边界检查,因为您使用指针作为类成员,所以我最好的猜测是您正在违反。也就是说,您没有为类提供复制构造函数和复制赋值运算符。在传递类的对象时,这通常会导致奇怪的数据丢失

注意,没有健全的C++程序员会使用<代码> char ***/COD>。下面是我使用向量和字符串修复问题的最佳尝试,但对于您的特定问题,可能有更好的设计:

#include <string>
#include <vector>

class Foo
{
    int m_iNumOfHeroes;
    std::vector<std::vector<std::vector<std::string> > > m_DataKeys;

    enum { NUM_OF_ABILITIES = 4, iNumOfExtraData = 2 };

public:

    explicit Foo(int iNumOfHeroes)
    : m_iNumOfHeroes(iNumOfHeroes)
    , m_DataKeys(m_iNumOfHeroes, std::vector<std::vector<std::string> >
                 (NUM_OF_ABILITIES, std::vector<std::string>(iNumOfExtraData)))
    {
    }
};

int main()
{
    Foo x(2);
}
#包括
#包括
福班
{
国际摩纳哥英雄;
std::向量m_数据键;
枚举{NUM_OF_能力=4,iNumOfExtraData=2};
公众:
显式Foo(int)
:m_inumofheromes(inumofheromes)
,m_数据键(m_,std::vector
(能力的数量,std::vector(iNumOfExtraData)))
{
}
};
int main()
{
foox(2);
}
如果您以前从未在构造函数中看到过冒号语法,那么这就是一个

<>我真的希望C++有数组边界检查< /p>
如果使用
foo.at(i)
语法而不是
foo[i]
,那么
std::vector
std::string
确实有边界检查。在调试模式下,即使 Fo[i] <代码>在VisualC++、Irc.< /P> < P>中启用了边界检查,但我认为您预期错误的事情发生(调试程序中的可视化显示将发生变化),即使代码看起来是正确的。 调试器显示
m_数据键
*m_数据键
**m_数据键
,这与
m_数据键
m_数据键[0]
m_数据键[0][0]
相同。当您更改
m_DataKeys[1]
时,您不会在调试器输出中注意到它


以下内容可能会帮助您:在我的调试器(MS Visual Studio 2005)中,如果您输入例如
m_数据键,5
作为监视表达式,您将看到数组的前5个元素,即,
m_数据键[0]
m_数据键[1]
,…,
m_数据键[4]
-排列在一个整洁的表格中。如果此语法(使用
,5
)对您不起作用,只需将
m_DataKeys[1]
添加到调试器的监视窗口中。

我认为您预期会发生错误的事情(调试器中的可视化显示会发生)
struct AbilityData
{
  // Stuff

  CUtlMap<char*,int[MAX_ABILITY_LEVELS]> ExtraData;
  char **DataKeys;
}
struct AbilityData
{
  // Stuff

  int *ExtraData;
  char **DataKeys;
}