Question

So this answer made me think about the scenario where you assign the result of new to a pointer to a const. AFAIK, there's no reason you can't legally const_cast the constness away and actually modify the object in this situation:

struct X{int x;};

//....
const X* x = new X;
const_cast<X*>(x)->x = 0; // okay

But then I thought - what if you actually want new to create a const object. So I tried

struct X{};

//....
const X* x = new const X;

and it compiled!!!

Is this a GCC extension or is it standard behavior? I have never seen this in practice. If it's standard, I'll start using it whenever possible.

Was it helpful?

Solution 2

const is part of the type. It doesn't matter whether you allocate your object with dynamic, static or automatic storage duration. It's still const. Casting away that constness and mutating the object would still be an undefined operation.

constness is an abstraction that the type system gives us to implement safety around non-mutable objects; it does so in large part to aid us in interaction with read-only memory, but that does not mean that its semantics are restricted to such memory. Indeed, C++ doesn't even know what is and isn't read-only memory.

As well as this being derivable from all the usual rules, with no exception [lol] made for dynamically-allocated objects, the standards mention this explicitly (albeit in a note):

[C++03: 5.3.4/1]: The new-expression attempts to create an object of the type-id (8.1) or new-type-id to which it is applied. The type of that object is the allocated type. This type shall be a complete object type, but not an abstract class type or array thereof (1.8, 3.9, 10.4). [Note: because references are not objects, references cannot be created by new-expressions. ] [Note: the type-id may be a cv-qualified type, in which case the object created by the new-expression has a cv-qualified type. ] [..]

[C++11: 5.3.4/1]: The new-expression attempts to create an object of the type-id (8.1) or new-type-id to which it is applied. The type of that object is the allocated type. This type shall be a complete object type, but not an abstract class type or array thereof (1.8, 3.9, 10.4). It is implementation-defined whether over-aligned types are supported (3.11). [ Note: because references are not objects, references cannot be created by new-expressions. —end note ] [ Note: the type-id may be a cv-qualified type, in which case the object created by the new-expression has a cv-qualified type. —end note ] [..]

There's also a usage example given in [C++11: 7.1.6.1/4].

Not sure what else you expected. I can't say I've ever done this myself, but I don't see any particular reason not to. There's probably some tech sociologist who can tell you statistics on how rarely we dynamically allocate something only to treat it as non-mutable.

OTHER TIPS

new obviously doesn't create a const object (I hope).

If you ask new to create a const object, you get a const object.

there's no reason you can't legally const_cast the constness away and actually modify the object.

There is. The reason is that the language specification calls that out explicitly as undefined behaviour. So, in a way, you can, but that means pretty much nothing.

I don't know what you expected from this, but if you thought the issue was one of allocating in readonly memory or not, that's far from the point. That doesn't matter. A compiler can assume such an object can't change and optimise accordingly and you end up with unexpected results.

My way of looking at this is:

  • X and const X and pointers to them are distinct types
  • there is an implicit conversion from X* to const X*, but not the other way around
  • therefore the following are legal and the x in each case has identical type and behaviour

    const X* x = new X; const X* x = new const X;

The only remaining question is whether a different allocator might be called in the second case (perhaps in read only memory). The answer is no, there is no such provision in the standard.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top