Modifying const object through pointer obtained during construction

const enforces "bitwise constness", but what you usually want is "logical constness".

In the case of an object that contains a pointer, this means that a const member function can't modify the pointer itself, but can modify what the pointer refers to. In other words, these examples are well formed, but have undefined behavior.

To get logical constness, you 1) use mutable (or sometimes const_cast) to allow modification of members that don't affect the object's logical state (e.g., cached values/memoization), and 2) generally have to manually enforce not writing to data through a pointer (but if it's an owning pointer, that ownership should probably be delegated to an object that only manages ownership of that data, in which case making it const should normally prevent writing to the data it owns).

As far as the specific detail of having a non-const pointer pointing to data that might itself have been const modified, well, you're basically just getting a (persistent) version of roughly the same thing that const_cast is typically used to do: get non-const access to data to which you'd otherwise only have a const pointer. It's up to you to ensure that you only use this in ways that doesn't cause a problem (but just having and/or writing through that pointer doesn't, in itself, necessarily lead to a problem).

In other words, what we have here are two separate pointers to some data. this lets you access an object's data. In a const member function, you can only read (not) write data via this, unless (as noted above) it's marked mutable. In this case, you're saving a second pointer to the same data. Since there's nothing to mark that as a pointer to const, it's not, so you get non-const access to the data it points at.


As others pointed out in comments: you are modifying object the m_ptr points to. This "pointed to" object is not a part of class Test (as far as compiler sees it). That's why compiler allows you to do so.

Having said that, I believe that it will be undefined behaviour. That's because m_ptr actually points to another member variable (m_val) of object const Test t! Compilers are allowed to optimize arggresively and they might rely on constness to do so.

The only exception is then you use mutable keyword, but it's another story.

Tags:

C++

Constants