我在这里遇到一些困难,希望有些人能帮助我。
我有以下内容,
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增加地址,继续创建指针,但我错过了一些非常严重的东西。
我真的很感谢你的帮助。
答案 0 :(得分:14)
在第二个示例中,您只分配了一个CandyBar
结构,但是您将其视为一个数组。这不会很好地结束,并且是缓冲区溢出的一种方法。
为了分配一个CandyBars
的数组,你需要告诉new你想要一个数组,如下所示:
CandyBar* bars = new CandyBar[3];
确保在删除CandyBars
数组时,您正在使用这样的数组删除:
delete[] bars;
所有这一切,在C ++生产代码中,您通常会使用std :: vector或std :: arrray来处理这种情况,因为您不必处理尽可能多的资源管理。情况下。
如果你必须在堆上动态分配数组并仍然使用RAII,我还会看boost::shared_array
和boost::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)。因此你的代码崩溃了。