我试图理解动态struct数组中与动态struct数组相关的内存问题。我正在动态创建一个结构数组并将其附加到变量' persons'然后动态创建一个结构数组并将其附加到变量' pets'在每个人的内部'宾语。一个简单的例子就是:
typedef struct {
int age;
} Pet;
typedef struct {
Pet *pets;
} Person
创建2个Object Person数组并将其附加到变量' persons'
persons = (Person*) ::operator new(sizeof(Person) * 2);
persons[0]
persons[1]
创建3个Object Pet数组并将其附加到变量' pets'在'
中对象#1的内部persons[0].pets = (Pet*) ::operator new(sizeof(Pet) * 3);
persons[0].pets[0].age
persons[0].pets[1].age
persons[0].pets[2].age
创建2个Object Pet数组并将其附加到变量' pets'在'
的对象#2内persons[1].pets = (Pet*) ::operator new(sizeof(Pet) * 2);
persons[1].pets[0].age
persons[1].pets[1].age
如果我动态创建另一个结构数组并将其附加到'人员'数组将先前附加到变量' person'是免费的吗?
创建4个Object Person数组并将其附加到变量' person'替换之前的2个Object数组。
persons = (Person*) ::operator new(sizeof(Person) * 4);
persons[0]
persons[1]
persons[2]
persons[3]
如果没有,我是否需要释放每只宠物' '人物的每个对象内部的数组阵列
这是在Arduino上运行的代码中。代码工作正常,似乎无限期地重复,没有任何打嗝,但这并不意味着它是合法的。
// DYNAMIC MEMORY
// OBJECTS
// Pet object
typedef struct {
char *name;
int age;
} Pet;
// Person object
typedef struct {
char *name;
int age;
int numberOfPets;
Pet *pets; // OBJECT 'Pet' is part of OBJECT 'Person'
} Person;
#define OBJECT_PET 0
#define OBJECT_PERSON 1
// DYNAMIC MEMORY HANDLING
// ARRAY Creation
void* createArray(int numberOfObjects, int typeOfObject) {
numberOfObjects;
int memorySize;
switch (typeOfObject) {
case OBJECT_PET:
Serial.print("Creating Pet array of ");
memorySize = sizeof(Pet) * numberOfObjects;
break;
case OBJECT_PERSON:
Serial.print("Creating Person array of ");
memorySize = sizeof(Person) * numberOfObjects;
break;
}
Serial.print(numberOfObjects);
Serial.println(" objects");
return ::operator new(memorySize);
}
// GLOBAL VARIABLES
Person *persons;
int numberOfPersons;
void createPersonsAndPetsFirst() {
numberOfPersons = 3;
// CREATE 3 empty Person objects [0, 1, 2]
persons = (Person*) createArray(numberOfPersons, OBJECT_PERSON);
// ENTER Specific Person information for Person #1
// Person #1 [0]
persons[0].name = "Larry";
persons[0].age = 19;
persons[0].numberOfPets = 2;
// CREATE 2 empty Pet objects for Person #1
persons[0].pets = (Pet*) createArray(persons[0].numberOfPets, OBJECT_PET);
// ENTER Specific Pet information for Pet #1
// Pet #1
persons[0].pets[0].name = "Xander";
persons[0].pets[0].age = 3;
// ENTER Specific Pet information for Pet #2
// Pet #2
persons[0].pets[1].name = "Shorty";
persons[0].pets[1].age = 6;
// ENTER Specific Person information for Person #2
// Persons #2 [1]
persons[1].name = "Mark";
persons[1].age = 29;
persons[1].numberOfPets = 1;
// CREATE 1 empty Pet object for Person #2
persons[1].pets = (Pet*) createArray(persons[1].numberOfPets, OBJECT_PET);
// ENTER Specific Pet information for Pet #1
// Pet #1 [0]
persons[1].pets[0].name = "Fido";
persons[1].pets[0].age = 5;
// ENTER Specific Person information for Person #3
// Person #3 [2]
persons[2].name = "Larry";
persons[2].age = 19;
persons[2].numberOfPets = 2;
// CREATE 2 empty Pet objects for Person #1
persons[2].pets = (Pet*) createArray(persons[0].numberOfPets, OBJECT_PET);
// ENTER Specific Pet information for Pet #1
// Pet #1
persons[2].pets[0].name = "Nado";
persons[2].pets[0].age = 12;
// ENTER Specific Pet information for Pet #2
// Pet #2
persons[2].pets[1].name = "Buster";
persons[2].pets[1].age = 4;
Serial.println();
}
void createPersonsAndPetsSecond() {
numberOfPersons = 2;
// CREATE 2 empty Person objects [0, 1]
persons = (Person*) createArray(numberOfPersons, OBJECT_PERSON);
// ENTER Specific Person information for Person #1
// Person #1 [0]
persons[0].name = "Chad";
persons[0].age = 22;
persons[0].numberOfPets = 1;
// CREATE 1 empty Pet object for Person #1
persons[0].pets = (Pet*) createArray(persons[0].numberOfPets, OBJECT_PET);
// ENTER Specific Pet information for Pet #1
// Pet #1
persons[0].pets[0].name = "Lucky";
persons[0].pets[0].age = 5;
// ENTER Specific Person information for Person #2
// Persons #2 [1]
persons[1].name = "Lisa";
persons[1].age = 36;
persons[1].numberOfPets = 2;
// CREATE 2 empty Pet objects for Person #2
persons[1].pets = (Pet*) createArray(persons[1].numberOfPets, OBJECT_PET);
// ENTER Specific Pet information for Pet #1
// Pet #1 [0]
persons[1].pets[0].name = "Chester";
persons[1].pets[0].age = 7;
// ENTER Specific Pet information for Pet #2
// Pet #2 [1]
persons[1].pets[1].name = "Marlo";
persons[1].pets[1].age = 12;
Serial.println();
}
void sendPersonsAndPetsInformationToHost() {
Serial.print("Number of Persons = ");
Serial.println(numberOfPersons);
for (int personsIndex = 0; personsIndex < numberOfPersons; personsIndex++) {
// SHOW Person
Serial.print("Person #");
Serial.print(personsIndex + 1);
Serial.println(" Information");
// SHOW Person Information
Serial.print("Name = ");
Serial.println(persons[personsIndex].name);
Serial.print("Age = ");
Serial.println(persons[personsIndex].age);
// SHOW Person number of Pets Information
Serial.print("Number of Pets = ");
Serial.println(persons[personsIndex].numberOfPets);
for (int petsIndex = 0; petsIndex < persons[personsIndex].numberOfPets; petsIndex++) {
// SHOW Pet
Serial.print("Pet #");
Serial.print(petsIndex + 1);
Serial.println(" Information");
Serial.print("Name = ");
Serial.println(persons[personsIndex].pets[petsIndex].name);
Serial.print("Age = ");
Serial.println(persons[personsIndex].pets[petsIndex].age);
}
Serial.println();
}
}
void setup() {
// OPEN Serial communication
Serial.begin(115200);
}
void loop() {
// CREATE First Persons and Pets Arrays
createPersonsAndPetsFirst();
// SEND Persons and Pets array information to Host
sendPersonsAndPetsInformationToHost();
delay(2000);
// CREATE Second Persons and Pets Arrays
createPersonsAndPetsSecond();
// SEND Persons and Pets array information to Host
sendPersonsAndPetsInformationToHost();
delay(2000);
}
答案 0 :(得分:1)
否以前分配的内存不会被释放。你将失去所有分配的内存。
通过覆盖persons
指针,您将丢失已分配存储的句柄。所以在你这样做之前,你必须打电话
::operator delete(persons[0].pets);
::operator delete(persons[1].pets);
::operator delete(persons);
这很丑陋,不是吗?出于这个原因,存在std::vector
容器。
#include <vector>
struct Person {
std::vector< Pet > pets;
};
std::vector< Person > persons(2);
persons[0].pets = std::vector< Pet >(2);
persons[1].pets = std::vector< Pet >(3);
persons = std::vector< Person >(3); // won't lose memory
答案 1 :(得分:0)
简而言之,不,你需要删除它们。
您创建的第一个Person数组将变为垃圾,因此您应该在将另一个数组指定给指针之前删除(释放)它。 (将“新”操作符视为访问内存位置的请求权限(密钥),因此如果您丢失了该位置的地址,则无法再使用它,也没有其他人可以使用(因为您拥有钥匙!)所以它变成了垃圾。)
现在,如果你删除Person数组,你仍然会将Pet数组作为垃圾,所以你应该先删除它们(否则你没有它们的地址,再次,垃圾!),然后删除人数组。
更好(和标准)的方法是为Person编写析构函数方法并删除其中的Pet数组。当Person对象被删除时,将自动调用析构函数。