Question

I have class Person as following :

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

Now I need to add two contructors. One taking no arguments, that inserts field values to dynamically allocated resources. Second taking (char*, int) arguments initialized by initialization list. Last part is to define a destructor showing information about destroying objects and deallocating dynamically allocated resources. How to perform this task ?

That's what I already have :

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

    Person(char* c, int i){
    }
};
Was it helpful?

Solution

In the default constructor, allocation of the char array should include its desired size, e.g.

this->name = new char[32];

Note that this size includes the terminating 0 character, so the effective length of names you can store in this array is 31.

In the parameterized constructor, you can simply assign the given parameters to your class members.

In the destructor, you need to deallocate dynamically allocated resources - make sure to use delete[] when, and only when, deallocating memory allocated with new[]:

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

Update: I missed this one: if you want to allocate age dynamically, you should declare it as int* age.

I assume that the point of this exercise is to practice dynamic allocation/deallocation; in this context, it is fine. However, in general, it is not good practice to dynamically allocate ints, and instead of char* you should almost always use std::string, which handles memory allocation for you automatically and safely.

OTHER TIPS

By using the C++ string class you can forget about manual (and dangerous) memory management:

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.
};

Also see this link for the reason why you should always use an initialization list instead of assignments in a constructor.

Given your declaration, you cannot initialize age to dynamically allocated memory, since age isn’t a pointer.

You could of course change the type of age to int*. But I wouldn’t do that, it serves no purpose. It’s not clear if the assignment is really asking for dynamic allocation (and if so – why?).

For name, on the other hand, you can proceed as noted by @Péter. But once again, this isn’t a very good solution in most cases because C++ offers the string class which wraps string manipuation nicely into a class. If the assignment permits this, use string in place of char* and dynamic memory allocation.

I recommend using string class instead of char*.

Something like this:

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;
};

You can also allocate just the memory you need to copy the name when you want to set it. Also, don't forget to free the allocated buffer when the object gets destroyed!

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);
        }
    }
};

Edit and answer to remarks :

  • simplified destructor following suggestion by Konrad Rudolf
  • I tend to always set unallocated and deallocated pointers to NULL to avoid picking random memory locations when the pointer is not used right, and unallocated pointers are also easier to spot in the debbuger.
  • I didn't pay attention that the second method was a constructor, I thought it was a setter... changed it.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top