Search code examples
c++c++11shared-ptrsmart-pointersdelete-operator

How do smart pointers choose between delete and delete[]?


Consider:

delete new std :: string [2];
delete [] new std :: string;

Everyone knows the first is an error. If the second wasn't an error, we wouldn't need two distinct operators.

Now consider:

std :: unique_ptr <int> x (new int [2]);
std :: unique_ptr <int> y (new int);

Does x know to use delete[] as opposed to delete?


Background: this question floated through my head when I thought array type qualification of pointers would be a handy language feature.

int *[] foo = new int [2]; // OK
int *   bar = new int;     // OK
delete [] foo;             // OK
delete bar;                // OK
foo = new int;             // Compile error
bar = new int[2];          // Compile error
delete foo;                // Compile error
delete [] bar;             // Compile error

Solution

  • Unfortunately, they don't know what delete to use therefore they use delete. That's why for each smart pointer we have a smart array counterpart.

    std::shared_ptr uses delete
    std::shared_array uses delete[]
    

    So, your line

    std :: unique_ptr <int> x (new int [2]);
    

    actually causes undefined behavior.

    Incidentally, if you write

    std :: unique_ptr<int[]> p(new int[2]);
                         ^^
    

    then delete[] will be used since you've explicitly requested that. However, the following line will still be UB.

    std :: unique_ptr<int[]> p(new int);
    

    The reason that they can't choose between delete and delete[] is that new int and new int[2] are exactly of the same type - int*.

    Here's a related question of using correct deleters in case of smart_ptr<void> and smart_ptr<Base> when Base has no virtual destructor.