For the purposes of these examples let's pretend we have the class Cat
:
#include <iostream>
#include <string>
using namespace std;
class Cat {
public:
Cat(string name = "unnamed") {
this->name = name;
}
string name;
};
This array lives on the call stack and is deallocated at the end of the scope it was created in. When it is deallocated it also deallocates every element in it's collection.
Cat array1[10]; // default constructors are called
cout << array1[0].name << endl; // "unnamed"
This array lives on the call stack and is deallocated at the end of the scope it was created in. When it is deallocated it does not deallocate the elements in it's collection. The
Cat* array2[10]; // no default constructors are called
cout << array2[0] << endl; // "0x0" (null pointer)
array2[0] = new Cat("Cat-Man");
cout << array2[0]->name << endl; // "Cat-Man"
// Delete data
delete array2[0]; // deletes first element
This array lives on the heap and needs to be explicitly deallocated.
Cat* array3;
array3 = new Cat[10]; // default initializers are called
cout << array3[0].name << endl; // "unnamed"
// Delete data
delete [] array3; // delete the allocated array on the heap and it's elements
This array lives on the heap and needs to be explicitly deallocated. It's elements also need to be explicitly deallocated.
Cat** array4;
array4 = new Cat*[10]; // no default constructors are called
cout << array4[0] << endl; // "0x0" (null pointer)
array4[0] = new Cat("Cat-Man");
cout << array4[0]->name << endl; // "Cat-Man"
// Delete data
delete array4[0]; // must delete each object by pointer
delete [] array4; // delete the allocated array on the heap