c++new-operatordelete-operatorconst-referenceconst-pointer

new-expression and delete-expression on const reference and const pointer


C++

Much literature says const references cannot be used to modify their referents and const pointers cannot be used to modify their pointees.

Then, why can they be deleted?

const int& cirDynamic = *( new int(5) );
// ^ 'const int& cirDynamic = *( &( *( new int(5) ) ) );' gives same output below
cout << cirDynamic << endl; // 5
delete &cirDynamic;
cout << cirDynamic << endl; // garbage value

I know the trailing const in T* const only prevents the pointer from being reseated, but below I use two consts, as in const T* const, for emphasis. Why can the following pointer be deleted?

const int* const cipcDynamic =  new int(5);
// ^ 'const int* const cipcDynamic = &( *( new int(5) ) );' gives same output below
cout << *cipcDynamic << endl; // 5
delete cipcDynamic;
cout << *cipcDynamic << endl; // garbage value

The output shows that at least some dynamically allocated memory was freed. Has all of it been freed, or could there have been copying involved where only the copy was freed?

The non-const version of the const reference snippet (int&) and the non-leading-const versions of the const pointer const snippet (int* const and int*) produce the same output as their more const counterparts. In all 5 cases, why and how is the lifetime of the temporary new-expression extended?

Assuming the corresponding operator has not been overloaded, explicitly deleted, or made non-public if the data type is a class or struct, does the Standard make the following guarantees:

If instead the new operator was overloaded but still returned ::operator new(size) and the dereference operator was overloaded but still returned a reference to the object, are there any side-effects that would make these two points not hold?


Solution

  • Constness affects objects themselves. new and delete and constructors affect the creation of objects. It doesn't make sense to ask whether constructors or destructors are const, because they run before or after the object exists. Similarly, you can create and destroy constant objects dynamically, and/or you can manage dynamically created objects through constant pointers or references.

    As a very simple thought experiment, consider this code:

    {
        const int x = 0;
    }
    

    This wouldn't work if constness could prevent the object x from being destroyed.