使用new创建一个结构数组

时间:2013-01-01 22:06:20

标签: c++ data-structures struct

我在这里遇到一些困难,希望有些人能帮助我。

我有以下内容,

struct CandyBar{ 
  std::string name; 
  double weight; 
  int calories; 
} ;

现在,创建一个包含许多CandyBars的结构数组非常简单,我已经做过了;

int main(){
   CandyBar bars[] = {{"Mango tart", 2.3, 100}, {"Yo Yo", 3.2, 130}, {"Orange Ball", 1.7, 98}};
  return 0;
}

但是,现在我想用new创建相同的结构。我认为这很简单,但这会崩溃并且不起作用。

CandyBar *bars = new CandyBar;
  (*bars).name = "Mango tart";
   bars->weight =  2.3;
   bars->calories =  100;
   bars += 1;

  (*bars).name = "Yo Yo";
  bars->weight =  3.2;
  bars->calories =  130;

  bars += 1;
  (*bars).name =  "Orange Ball";
  bars->weight =  1.7;
  bars->calories =  98; 

但是,这不起作用。因为我认为第一个指针是指向第一个结构的内存位置,然后我创建结构,然后使用bar + = 1增加地址,继续创建指针,但我错过了一些非常严重的东西。

我真的很感谢你的帮助。

4 个答案:

答案 0 :(得分:14)

在第二个示例中,您只分配了一个CandyBar结构,但是您将其视为一个数组。这不会很好地结束,并且是缓冲区溢出的一种方法。

为了分配一个CandyBars的数组,你需要告诉new你想要一个数组,如下所示:

CandyBar* bars = new CandyBar[3];

确保在删除CandyBars数组时,您正在使用这样的数组删除:

delete[] bars;

所有这一切,在C ++生产代码中,您通常会使用std :: vector或std :: arrray来处理这种情况,因为您不必处理尽可能多的资源管理。情况下。

如果你必须在堆上动态分配数组并仍然使用RAII,我还会看boost::shared_arrayboost::scoped_array.

答案 1 :(得分:6)

只为一个CandyBar分配空间,因此您正在写入未分配的堆内存。这是一个禁忌。你真的很幸运,它失败了,因为它有能力产生非常difficult to debug problems

您可以为更多CandyBar分配空间:

CandyBar *bars = new CandyBar[3]; // 3 CandyBars.

...并且不要忘记使用像这样的数组deletor:

delete[] bars;

但是,仍有能力超出您分配的CandyBar个数。在C ++中这样做的首选方法是使用std::vector

在此示例中,我为CandyBar提供了一个构造函数,用于缩写并将它们放入std::vector

#include <string>
#include <vector>

struct CandyBar{ 
  std::string name;
  double weight;
  int calories;
  CandyBar(std::string name, double weight, int calories)
  {
      this->name = name;
      this->weight = weight;
      this->calories = calories;
  }
};

int main()
{
    std::vector<CandyBar> bars;
    bars.push_back(CandyBar("Mango tart", 2.3, 100));
    bars.push_back(CandyBar("Yo Yo", 3.2, 130));
    bars.push_back(CandyBar("Orange Ball", 1.7, 98));

    return 0;
}

没有new,没有delete,没有泄密,没有腐败。

我还想补充一点,如果您使用的编译器支持某些C ++ 11并且不希望std::vector为您提供动态分配,您可以考虑使用std::array代替。

答案 2 :(得分:1)

Foo * a = new Foo仅为Foo的一个实例分配空间。如果要分配Foo数组,则需要使用Foo * a = new Foo[ARRAY_LEN]


基本上,你真正想做的是动态分配一些内存来保存一个对象数组,在你的CandyBar个对象中。问题是,你正在使用new运算符,它只为一个这样的对象分配内存。然后,您尝试使用返回的内存地址,就像它指向一个数组一样。您将不可避免地尝试访问尚未分配的内存,这将导致分段错误(充其量)。

您真正需要的运算符是new[]运算符(调用为new CandyBar[ARRAY_LEN]),它为指定数量的对象的数组分配足够的内存。然后,您可以获取返回的内存地址,并将其视为您提供的大小数组,而不必担心会超出内存分配。

通常,如果您正在处理可能在程序的整个生命周期中增长或缩小的CandyBar集合,那么分配固定大小的数组是不可取的。看看C ++ STL中的std::vector模板类 - std::vector<CandyBar>可以根据您要存储的CandyBar的数量动态增长或缩小,并且可以像对待foo[42]一样自由访问它是一个数组(例如{{1}})。

答案 3 :(得分:0)

您应该使用以下内容分配CandyBar数组:

CandyBar *bars = new CandyBar[20];

然后您使用bars[0]bars[1] ... bars[19]等来访问各个糖果栏。

请注意,您的代码bars + 1会向指针添加一个sizeof CandyBar,但这会指向未分配的区域(因为您刚刚分配了一个CandyBar)。因此你的代码崩溃了。