动态创建包含另一个动态创建的结构数组

时间:2015-05-06 16:11:30

标签: c++ arrays dynamic struct arduino

我试图理解动态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); 

}

2 个答案:

答案 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

由于您可能没有听说过,我建议您阅读RAIIhere

答案 1 :(得分:0)

简而言之,不,你需要删除它们。

您创建的第一个Person数组将变为垃圾,因此您应该在将另一个数组指定给指针之前删除(释放)它。 (将“新”操作符视为访问内存位置的请求权限(密钥),因此如果您丢失了该位置的地址,则无法再使用它,也没有其他人可以使用(因为您拥有钥匙!)所以它变成了垃圾。)

现在,如果你删除Person数组,你仍然会将Pet数组作为垃圾,所以你应该先删除它们(否则你没有它们的地址,再次,垃圾!),然后删除人数组。

更好(和标准)的方法是为Person编写析构函数方法并删除其中的Pet数组。当Person对象被删除时,将自动调用析构函数。