繁体   English   中英

使用* pointer array C ++设置构造函数和析构函数

[英]Setting constructor and destructor with *pointer array C++

我正在使用int *studentsAge存储年龄列表,并使用double *marks[2]存储每个学生2个分数的列表。

基本上,我不确定如何设置constructordestructor

这是我的构造函数...

Students::Students()
{
  num = 0;
  studentsAge = NULL;
  marks[2] = NULL;
}

我在此函数中同时使用了两个指针数组。

void Students::storeValues(int num)
{
   this->num = num;
   studentsAge = new int[num];
   for(int i=0; i<num; i++)
   {
     studentsAge[i] = i;
     marks[i] = new double[num]
   }
}

这是我的破坏者...

Students::Students()
{
   for(int i=0; i<num; i++)
   {
      delete[] marks[i];
      delete[] studentAge[i];
   }
   delete[] marks;
   delete[] studentAge
}

我不确定我的constructordestructor是否正确,并且我可以怀疑某个地方存在内存泄漏。 我不太擅长使用指针,但是如果有人可以告诉我我要去哪里错了,我将不胜感激

让每个学生在一起的更好的设计是:

struct Student
{
    int marks[2];
    int age;
};

然后存储一个学生容器:

struct Students
{
    std::vector<Student> students;
    void storeValues(int num);
}

您的函数如下所示:

void Students::storeValues(int num)
{
    students.resize(num, Student());   // zero-initialized students!

    for(int i=0; i<num; i++)
        students[i].age = i;
}

这样,您无需编写任何析构函数或“五规则”中的任何其他函数,因此可以减少出错的机会,并避免浪费时间编写样板代码。

没有理由使用您的2元素标记数组。 让自己轻松一点,并将其更改为2 double *的marks0和marks1。

double* marks0;
double* marks1;

但是,如果要继续在当前路径上运行,首先需要正确初始化标记:

Students::Students()
{
    num = 0;
    studentsAge = NULL;
    marks[0] = NULL;     //clear the pointer to the first array of marks
    marks[1] = NULL;     //clear the pointer to the second array of marks
}

现在,您需要正确创建标记数组:

void Students::storeValues(int num)
{
   this->num = num;
   studentsAge = new int[num];
   marks[0] = new double[num];
   marks[1] = new double[num];
   for(int i=0; i<num; i++)
   {
     studentsAge[i] = i;  //what is this doing?  each student's age is the same as his/her index?
     marks[0][i] = 0;     //initialize the first mark for student i
     marks[1][i] = 0;     //initialize the second mark for student i
   }
}

最后,您需要正确销毁阵列​​:

Students::~Students()
{
   delete[] marks[0];
   delete[] marks[1];
   delete[] studentsAge;
}

我想就您的主要领域而言,您的Student类看起来像这样:

class Students
{
   private:
    static const int maxNumberMarks = 2;  //the maximum number of marks that can be stored per student
    int numStudents;                      // the count of the number of students
    int* studentsAge;                     // an array of each students ages   
    double* marks[maxNumberMarks];        // an array of arrays to store each student mark
}

在这种情况下,您的默认构造函数几乎正确。 您只需要正确地初始化标记数组即可。

Students::Students()
{
   num = 0;
   studentsAge = NULL;
   for( int markIndex = 0; markIndex  < maxNumberMarks; ++markIndex )
   {
       marks[markIndex ] = NULL;
    }
}

您的初始化功能有些混乱。

首先,我将输入num arg重命名为numStudents之类的名称,以免与同名的成员变量混淆。

其次,您需要从初始化数组中分离出数组的分配

void Students::storeValues(int numStudents )
{
  this->num = numStudents ; //store off how many students we are handling.

  //allocate 3 storage arrays for each student. The age array and 2 mark arrays 
  studentsAge = new int[numStudents ];
  for( int markIndex =0; markIndex < maxNumberMarks; ++markIndex)
  {
     marks[markIndex] = new double[numStudents];
  } 

  //now init the arrays to something 
  for(int studentIndex=0; studentIndex < numStudents ; studentIndex++)
  {
     studentsAge[studentIndex] = studentIndex;
     for( int markIndex =0; markIndex < maxNumberMarks; ++markIndex)
     {
        marks[markIndex][studentIndex] = 0.0; //zero seems a reasonable initial value.
     }
  }
}

最后,要获取析构函数,您只需镜像分配数组的代码。

~Students()
{
   //delete the marks arrays 
    for( int markIndex =0; markIndex < maxNumberMarks; ++markIndex)
    {
       delete[] marks[markIndex];
       marks[markIndex] = NULL;
     } 

   //delete the ages array
   delete[] studentsAge;
   studentsAge = NULL;
}

随着代码的增长,您可能希望为每个学生存储不同的数据,我建议创建一个Student类以帮助简化所有内容。

class Student
{
  private:
    static const int maxNumberMarks = 2;  //the maximum number of marks that can be stored per student
    int age; //the age of the student
    double marks[maxNumberMarks];
 }

假设您使用适当的Default构造函数充实了Student数组,这将简化所有分配到Student类中一个位置的所有操作

Students
{
   Student* studentsArray;  //dynamically  allocated array of student info
   int numStudents;     
 }

 void Students::storeValues(int numStudents )
 {
    this->num = numStudents ;
    studentsArray = new Student[numStduents];
 }

 ~Students()
 {
   delete[] studentsArray;
   studentsArray = NULL;
 }

而且,如果您使用std :: vector代替分配的数组,则您甚至不必担心分配和释放它。

简短答案:

您需要编写以下内容:

Students::Students()
{
  num = 0;
  studentsAge = NULL;
  marks[0] = NULL;
  marks[1] = NULL;
}

void Students::storeValues(int num)
{
   this->num = num;
   studentsAge = new int[num];
   marks[0] = new int[num];
   marks[1] = new int[num];

   for(int i=0; i<num; i++)
   {
     studentsAge[i] = i; // this is where you give each student an age, are you sure you want to use i?
     // here you can put grade assignments as follows:
     marks[0][i] = val1; // first mark for student i
     marks[1][i] = val2; // second mark for student i
   }
}

Students::~Students()
{
   delete[] marks[0];
   delete[] marks[1];
   delete[] studentsAge;
} 

长答案:

似乎您需要了解什么是指针以及什么是数组。

当您在类声明中放置double *marks[2]时,它将保留附加到该类每个实例的双精度指针大小为2的数组。 您无需将[2]放入构造函数中。

指针是一个变量,用于保存内存中保留地址块的第一个地址。 这意味着当您分配一个指针时,需要给它一个内存地址。 要将值写入指针中存储的地址,请在变量前使用*字符。

int num = 2;
int* p;

p = &num; // p will hold the address of num.  Any changes to p's value will be reflected in num

p = new int; // p is assigned a new address
*p = num; // the address that p points to will hold 2 (the value in num), but if that value is changed, num will still hold 2

如果要为p分配一个数组,则可以使用new关键字。 这将为程序分配内存。 不要忘记取消分配它。

size = 10;
p = new int[size];

现在您可以通过将p当作数组或指针算术来引用p的值,我现在不再赘述。

p[0] = 1; // the first 
p[5] = 56;

指针和数组之间的区别在于数组分配和释放是由编译器处理的,并且在编译时需要具有固定的大小。 指针的分配和释放由用户处理,其大小在运行时定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM