26

Consider this

class Foo
{
public:
    Foo(){}
    ~Foo(){}
    void NonConstBar() {}
    void ConstBar() const {}
};

int main()
{
    const Foo* pFoo = new Foo();
    pFoo->ConstBar(); //No error
    pFoo->NonConstBar(); //Compile error about non const function being invoked
    delete pFoo; //No error 

    return 0;
}

In the main function I am calling both const and non const functions of Foo

Trying to call any non const function yields an error in Visual Studio like so

error C2662: 'Foo::NonConstBar' : cannot convert 'this' pointer from 'const Foo' to 'Foo &'

But delete pFoo doesn't issue any such error. The delete statement is bound to call the destructor of Foo class which doesn't have a const modifier. The destructor is also allowed to call other non const member functions. So is it a const function or not ? Or is delete on a const pointer a special exception?

parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85
  • 1
    Constructor is most surely considered as initialization, not modification of the instance. The same for destructor. It doesn't modify the instance, it destroys is. – Roman Byshko Dec 04 '11 at 01:06
  • 12
    ¤ In pre-standard C++ as defined by the Annotated Reference Manual you could not do `delete p` when `p` was of type `T const*`. During the standardization (C++ was standardized in 1998) this rule was reversed, it was both impractical and inconsistent. With the rules of standard C++ an object is mutable during construction, no matter the client code's type; if the declared type is `const` it then becomes immutable for its main lifetime span; and finally for destruction the construction process is reversed, which means that it again is mutable. And which means you can `delete p`. Cheers & hth., – Cheers and hth. - Alf Dec 04 '11 at 01:18
  • 2
    @Alf... I think your comment should be an answer – parapura rajkumar Dec 05 '11 at 16:04
  • See also http://stackoverflow.com/questions/2271046/if-changing-a-const-object-is-undefined-behavior-then-how-do-constructors-and-de – nos Apr 14 '15 at 13:48
  • [standard's paragraph](http://eel.is/c++draft/class.dtor#2). also you can destroy it explicitly. But with delete it's another story (another paragraph). – Volodymyr Boiko Feb 03 '17 at 19:20

2 Answers2

23

You can delete objects thorough constant pointers. In C++11, you can an also erase container elements through const-iterators. So yes, in a sense the destructor is always "constant".

Once the destructor is invoked, the object has ceased to exist. I suppose the question of whether a non-existing object is mutable or not is moot.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    I don't know if I buy the last part of your argument. A const pointer is meant to prevent you from modifying an object's state, and destroying it certainly does that. – Mark Ransom Dec 04 '11 at 01:11
  • 1
    @MarkRansom: On the other hand, I can only modify an object that *exists*. I can certainly *enter* the destructor, like any member function; but already at this step, the object ceases to exist -- not because of what the destructor *does*, but merely by the fact that the control flow has reached that point. *Now* the destructor can do its work without regard to what it's doing to the erstwhile object. – Kerrek SB Dec 04 '11 at 01:13
  • 2
    @MarkRansom: given that you can destroy objects through const pointers in C++, *either* destroying it is not "modifying its state", *or* a const pointer is not "meant to prevent you from modifying its state". This isn't an accident of the language, it's totally deliberate, so while you might not like it, if you consider destruction to be modification then it is false to claim that the language is designed to prevent all modification via const pointers. – Steve Jessop Dec 04 '11 at 01:18
  • @SteveJessop, I wasn't saying I disagree with the standard behavior. I just said I didn't think the argument is valid. At the time you try to destroy the object it does still exist, and the compiler could easily disallow it if that's what the standard called for. As you say it's deliberately allowed, so I think it must be a special case rather than a "moot point". I think Alf's comment on the question supports this view. – Mark Ransom Dec 04 '11 at 02:28
  • @Mark: I think what's "moot" is whether you decide that destruction is mutation (and conclude that objects can, as a special case, be mutated in this way through a const pointer), or decide that destruction is not mutation (and conclude that objects cannot be mutated through a const pointer, but can be destroyed). If you focus on what Alf said that the prior rule was "impractical", you conclude it's a special case. If you focus on the prior rule being "inconsistent", you conclude that this isn't a special case at all, destruction logically was never mutation and the ARM got it wrong. Moot ;-) – Steve Jessop Dec 04 '11 at 02:42
  • @Steve, I agree with everything you just said. Nice summary. – Mark Ransom Dec 04 '11 at 03:04
5

The lifetime of an object ends (for the owner/enclosing scope) as soon as the destructor is invoked, not when the destructor returns.

Therefore I don't see any problem deleting constants. It's already gone for you when you call delete.

Otherwise deleting constant objects would require a const_cast.

FailedDev
  • 26,680
  • 9
  • 53
  • 73
  • "Otherwise deleting constant objects would require a `const_cast`." No, it would be impossible. `const_cast` does not allow mutating constant objects. It provides compatibility with APIs that aren't const-correct (pointers and references not used to mutate the object, but marked non-`const`) as well as recovering a non-`const` handle to a non-`const` object from a `const` handle. But any attempt to modify a constant object is illegal, irrespective of whether you used `const_cast` first. It does not "unlock" a constant. – Ben Voigt Mar 06 '18 at 16:45