0

我有类 Person 如下:

class Person {   
    char* name;
    int age;
};

现在我需要添加两个构造函数。一种不带参数,将字段值插入动态分配的资源。第二次采用由初始化列表初始化的 (char*, int) 参数。最后一部分是定义一个析构函数,显示有关销毁对象和重新分配动态分配的资源的信息。如何执行此任务?

这就是我已经拥有的:

class Person {   
    char* name;
    int age;
public:
    Person(){
        this->name = new *char;
        this->age = new int;
    }

    Person(char* c, int i){
    }
};
4

5 回答 5

3

在默认构造函数中,char 数组的分配应包括其所需的大小,例如

this->name = new char[32];

请注意,此大小包括终止字符 0,因此您可以存储在此数组中的名称的有效长度为 31。

在参数化构造函数中,您可以简单地将给定的参数分配给您的类成员。

在析构函数中,您需要释放动态分配的资源 - 确保delete[]在且仅在释放分配的内存时使用new[]

~Person(){
    std::cout << "Destroying resources" << std::endl;
    delete[] name;
    delete age;
}

更新:我错过了这个:如果你想age动态分配,你应该将它声明为int* age.

我假设这个练习的重点是练习动态分配/释放;在这种情况下,这很好。但是,一般来说,动态分配 s 并不是一个好习惯int,而char*您应该几乎总是使用std::string,它会自动且安全地为您处理内存分配。

于 2010-05-18T10:00:55.343 回答
2

通过使用 C++string类,您可以忘记手动(和危险的)内存管理:

class Person {
    public:
        Person () : name_(""), age_(0) { }
        Person (const std::string& name, int age) : name_(name), age_(age) { }
    // There is no need for the destructor as the memory is managed by the string class.
};

请参阅此链接,了解为什么您应该始终在构造函数中使用初始化列表而不是赋值。

于 2010-05-18T10:43:45.927 回答
1

鉴于您的声明,您无法初始化age为动态分配的内存,因为age它不是指针。

您当然可以将类型更改ageint*。但我不会那样做,它没有任何意义。目前尚不清楚分配是否真的要求动态分配(如果是,为什么?)。

name另一方面,您可以按照@Péter 的说明进行操作。但是,在大多数情况下,这又不是一个很好的解决方案,因为 C++ 提供的string类可以很好地将字符串操作包装到一个类中。如果分配允许这样做,请使用动态内存分配string代替。char*

于 2010-05-18T10:12:26.123 回答
0

您还可以在需要设置名称时仅分配复制名称所需的内存。另外,不要忘记在对象被销毁时释放分配的缓冲区!

class Person {   
    char* name;
    int age;
public:
    Person(){
        this->name = NULL;
        this->age = 0; // no need to allocate memory for basic types
    }

    ~Person(){
        delete [] name;
    }

    set(char* c, int i){
        this->age = i;

        // copy name if input pointer name is valid
        if (c != NULL){
            // if memory have already been allocated : delete first
            if (this->name != NULL){
                delete [] name;
                name = NULL;
            }
            // allocate memory : 1 more char for the trailing '\0'
            this->name = new char[strlen(c)+1];
            // copy string
            strcpy(this->name,c);
        }
    }
};

编辑并回复评论:

  • 根据 Konrad Rudolf 的建议简化析构函数
  • 我倾向于总是将未分配和解除分配的指针设置为 NULL 以避免在指针未正确使用时选择随机内存位置,并且未分配的指针也更容易在调试器中发现。
  • 没注意第二个方法是构造函数,还以为是setter……改了。
于 2010-05-18T10:11:59.967 回答
0

我建议使用字符串类而不是 char*。

像这样的东西:

class Person
{
 public:
  Person() : name(""), age(0) {}
  Person(const string& n, int a) : name(n), age(a) {}

  // whatever here.

  ~Person() {} // do nothing

 private:
  string name;
  int age;
};
于 2010-05-18T11:34:12.447 回答