作为一个从不处理释放内存等问题的人,我的任务是创建一个动态的struct数组,并创建函数来添加或删除数组元素。删除时我必须释放不再需要的内存。
当删除大小为3的数组的第二个元素时,我将第3个元素移动到第2个位置然后删除最后一个元素。删除最后一个时,我总是收到错误...有没有人可以为我找到解决方案?
struct myFriend {
myFriend() {
number=0;
hobbys = new char*[10];
}
int number;
char* name;
char** hobbys;
};
int main() {
myFriend* friendList = new myFriend[10];
myFriend* tempFriend = new myFriend;
tempFriend->number=1;
tempFriend->name = "ABC";
myFriend* tempFriend2 = new myFriend;
tempFriend2->number=2;
tempFriend->name = "XYZ";
myFriend* tempFriend3 = new myFriend;
tempFriend3->number=3;
tempFriend3->name = "123";
friendList[0] = *tempFriend;
friendList[1] = *tempFriend2;
friendList[2] = *tempFriend3;
friendList[1] = friendList[2]; //move 3rd element on 2nd position
delete &(friendList[2]); //and delete 3rd element to free memory
}
答案 0 :(得分:2)
为什么要创建临时变量?他们甚至都不需要。
如果您使用std::vector
和std::string
,您遇到的问题将自动消失:
std::vector<myFriend> friendList(10);
friendList[0]->number=1;
friendList[0]->name = "ABC";
friendList[1]->number=2;
friendList[1]->name = "XYZ";
friendList[2]->number=3;
friendList[2]->name = "123";
要使其有效,您应该将结构重新定义为:
struct myFriend {
int number;
std::string name;
std::vector<std::string> hobbys;
};
如果你被要求使用原始指针,那么你应该做这样的事情:
struct Friend
{
int number;
char* name;
};
Friend * friends = new Friend[3];
friends[0]->number=1;
friends[0]->name = new char[4];
strcpy(friends[0]->name, "ABC");
//similarly for other : friends[1] and friends[2]
//this is how you should be deleting the allocated memory.
delete [] friends[0]->name;
delete [] friends[1]->name;
delete [] friends[2]->name;
delete [] friends; //and finally this!
如果您执行以下任何操作,那将是错误的,并会调用未定义的行为:
delete friends[2]; //wrong
delete &(friends[2]); //wrong
答案 1 :(得分:2)
无法从new []
myFriend* friendList = new myFriend[10];
你有一个完整的数组
+------------------------------------------------------------------+
| friendList[0] | friendList[1] | ..... | friendList[9] |
+------------------------------------------------------------------+
你不能delete &(friendList[2])
。
你可以从C++
获得整个10个元素的数组。
此数组从friendList
(或&(friendList[0])
)开始。
operator delete
指向new
返回的地址(即friendList
)的指针有效
仅
答案 2 :(得分:2)
我发现了两件事。 (1)你显然应该“创建添加或删除元素的函数”但是你还没有这样做,你只创建了一个函数。 (2)通过使用也需要管理内存的结构,您正在使您的工作更加困难。我建议你使用一个更简单的结构。
你的作业实际上是制作一个简单的“矢量”类,所以我建议你这样做。从一个空的结构开始。如果教师要求您使用所编写的myFriend
结构,则可以在之后在中添加该结构,以完成向量之类的函数。我会假设你还没有上课,因为大多数教练都会犯这样的错误,直到最后一次。
struct MyStruct {
int value; // start with just one value here. Dealing with pointers is more advanced.
};
MyStruct* array;
int size;
int capacity;
void addMyStruct(MyStruct& value); // adds a MyStruct object to the end.
void removeMyStructAtPosition(int position); // removes the MyStruct object that is at 'position'
// I leave the functions for you to implement, it's your homework after all, but I give some clues below.
void addMyStruct(MyStruct& value) {
// First check that there is enough capacity in your array to hold the new value.
// If not, then make a bigger array, and copy all the contents of the old array to the new one.
// (The first time through, you will also have to create the array.)
// Next assign the new value to array[size]; and increment size
}
void removeMyStructAtPosition(int position) {
// If the position is at end (size - 1,) then simply decrement size.
// Otherwise you have to push all the structs one to the left (array[i] = array[i + 1])
// from position to the end of the array.
}
int main() {
// test your new class here.
// don't forget to delete or delete [] any memory that you newed.
}
答案 3 :(得分:0)
数组大小固定为10,因此您无需从中删除任何元素。但您确实需要删除name
的{{1}}和hobbys
元素(以及之前覆盖它)。这里有两个问题:
friendList[1]
此处,friendList[0]->name = "ABC";
是内存中某处的常量零终止字符串。您不能删除它。所以你必须复制一份。 "ABC"
。但在您的代码中,您无法判断它是否已分配。因此,您必须在构造函数中将每个元素设置为0,以便稍后知道要删除哪些元素。 删除这些元素的正确位置在hobby[i]
的析构函数中。
答案 4 :(得分:0)
问题的关键在于管理动态数组。主要问题是他正在使用friendList数组。使用指向friendList的指针数组:
struct myFriend {
myFriend() {
number=0;
hobbys = new char*[10];
}
int number;
char* name;
char** hobbys;
};
int main() {
myFriend** friendList = new myFriend*[10];
myFriend* tempFriend = new myFriend;
tempFriend->number=1;
tempFriend->name = "ABC";
myFriend* tempFriend2 = new myFriend;
tempFriend2->number=2;
tempFriend->name = "XYZ";
myFriend* tempFriend3 = new myFriend;
tempFriend3->number=3;
tempFriend3->name = "123";
friendList[0] = tempFriend;
friendList[1] = tempFriend2;
friendList[2] = tempFriend3;
friendList[1] = friendList[2]; //move 3rd element on 2nd position
delete friendList[2]; //and delete 3rd element to free memory
}
但是其他人都是对的 - 对于“hobbys”和“name”的内存分配存在主要问题,需要单独排序。
答案 5 :(得分:0)
为了完成你的作业我建议学习更多关于指针,新/删除操作符,new [] / delete []操作符(不要与new / delete操作符混淆)和对象创建/复制/构造函数/析构函数。这是基本的C ++功能,你的任务就是这个。
指出一些方向:
1)当你像这样动态分配对象时
MyType* p = new MyType;
或
MyType* p = new MyType(constructor_parameters);
你得到指针p
到创建的对象(new
为类型MyType
的单个对象分配内存并调用该对象的构造函数。
完成对该对象的处理后,您必须致电
delete p;
delete
调用对象的析构函数然后释放内存。如果你不打电话delete
,你的记忆就会泄露。如果你不止一次调用它,行为是未定义的(可能是堆损坏,可能导致程序崩溃 - 有时是在非常奇怪的时刻)。
2)当你像这样动态分配数组时
MyType* p = new MyType[n];
你得到指针p
到n
已创建对象的数组,这些对象按顺序位于内存中(new[]
为n
分配单个内存块类型为MyType
的对象,并为每个对象调用默认构造函数。)
您无法更改此动态数组中的元素数。你只能删除它。 完成对该阵列的处理后,您必须调用
delete[] p; // not "delete p;"
delete[]
调用数组中每个对象的析构函数,然后释放内存。如果你不打电话delete[]
,你的记忆就会泄露。如果您多次调用它,则行为未定义(可能是程序崩溃)。如果你调用delete
而不是delete[]
,行为是未定义的(可能只为第一个对象调用析构函数,然后尝试释放内存块 - 但可能是任何东西)。
3)当你分配struct / class时,会调用operator=
。如果没有为struct / class明确定义operator=
,则生成隐式operator =(它执行struct / class的每个非静态成员的赋值)。