Having:
int* const p;
... does not disallow operator delete from being called on p. Having const int*
also does not disallow operator delete from being called on it.
Typical operator delete implementations take void* and any pointer will be implicitly cast to it (actually this might be the standard behavior to take void* or the only reasonable way to implement one global operator delete which can delete anything). Also as an interesting tidbit, one can implement their own overloaded operator delete (either globally or per-class) which takes void* and only has to free the memory allocated by new. The destructor call is implicitly added before any call to operator delete by the compiler; operator delete does not call the dtor in its implementation.
It is also worth noting that having const Test&
in this case basically modifies the member, int* p
so that it's analogous to int* const p
, not int const* p
or const int* p
.
Thus:
Test::Test(const Test& other)
{
*other.p = 123; // this is valid
other.p = NULL; // this is not valid
}
In other words, the pointer address is immutable, but the pointee is not. I've often encountered a lot of confusion here with respect to member function constness and the effect it has on data members which are pointers. Understanding this will give a little insight as to one of the reasons why we need the separation between iterator and const_iterator.