如何释放动态struct数组的内存

时间:2011-04-22 11:17:53

标签: c++ arrays memory delete-operator

作为一个从不处理释放内存等问题的人,我的任务是创建一个动态的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
}

6 个答案:

答案 0 :(得分:2)

为什么要创建临时变量?他们甚至都不需要。

如果您使用std::vectorstd::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元素(以及之前覆盖它)。这里有两个问题:

  1. 您正在设置friendList[1]此处,friendList[0]->name = "ABC";是内存中某处的常量零终止字符串。您不能删除它。所以你必须复制一份。
  2. 您希望在分配时删除"ABC"。但在您的代码中,您无法判断它是否已分配。因此,您必须在构造函数中将每个元素设置为0,以便稍后知道要删除哪些元素。
  3. 删除这些元素的正确位置在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];

你得到指针pn已创建对象的数组,这些对象按顺序位于内存中(new[]n分配单个内存块类型为MyType的对象,并为每个对象调用默认构造函数。)

您无法更改此动态数组中的元素数。你只能删除它。  完成对该阵列的处理后,您必须调用

delete[] p;  // not "delete p;"

delete[]调用数组中每个对象的析构函数,然后释放内存。如果你不打电话delete[],你的记忆就会泄露。如果您多次调用它,则行为未定义(可能是程序崩溃)。如果你调用delete而不是delete[],行为是未定义的(可能只为第一个对象调用析构函数,然后尝试释放内存块 - 但可能是任何东西)。

3)当你分配struct / class时,会调用operator=。如果没有为struct / class明确定义operator=,则生成隐式operator =(它执行struct / class的每个非静态成员的赋值)。