5

As far as I know in C++ struct/class members with the same access control are stored in memory in declaration order. Is next example m and c should be stored one after the other:

#include <cstdlib>
#include <iostream>

struct X
{
    mutable int m;
    int         c;
};

const X cx = {0, 1};

int main()
{   
    X& x = const_cast<X&>(cx);

    x.m = rand();
    x.c = rand();

    std::cout<<x.m<<" "<<x.c;
}

In this example the program runs and prints 2 random numbers. If I remove mutable it crashes because cx is stored in readonly protected memory.

This made me wonder - does one mutable member disable const optimizations for the entire struct(somehow make all members mutable)?

Is it possible to store parts of a struct in readonly memory and other parts on non-readonly memory and respect C++ standard memory layout?

This was tested using Visual Studio 2010 on Windows 7 and GCC 4.7.2 on Ubuntu.

3 Answers 3

5

The standard talks about mutable members in many places. I quote below three parts of the standard explaining that you can modify only the mutable members of a const object. Otherwise it is Undefined Behaviour.

3.9.3 CV-qualifiers [basic.type.qualifier]

A const object is an object of type const T or a non-mutable subobject of such an object.

[...]

7.1.1 Storage class specifiers [dcl.stc]

The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const.

[...]

7.1.6.1 The cv-qualifiers [dcl.type.cv]

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.


Is it possible to store parts of a struct in readonly memory and other parts on non-readonly memory and respect C++ standard memory layout?

No, it is impossible to store a parts of a struct (or class) in a different memory area than the rest of the object.

2
  • So the x.c = rand(); in main triggers UB in both cases, correct?
    – Hulk
    Commented Sep 3, 2013 at 7:45
  • @Hulk Yes, the mutable keyword on m does not change anything for c. Look at this post: stackoverflow.com/a/583150/1394283. It explains well the last part of the standard I quote. Commented Sep 3, 2013 at 7:53
4

To explain why the compiler has to do "all or nothing" when it comes to where to store the struct: In most processors, memory pages are 4KB (a few has 8KB pages). That is the granularity of "read only" vs "read/write" memory blocks. So you can't have one 4-byte integer in read-only memory, and then the next 4 byte integer in read-write memory (unless they are exactly straddling a 4KB memory boundary - but that would definitely make for quite wasteful use of memory if you have an array of 3000 of them, taking up 12MB).

Note that this is not an "optimisation". Read-only memory is not faster than read-write memory. It's a protection against users being silly with const and writing to the data they shouldn't write to.

Also if you add a constructor that "does something" to your struct, it will most likely store the struct in read-write memory, because it's quite tricky for the compiler to generate code to switch read-only on and off at runtime.

1
  • I added X() constructor that inits m and c and cx is not in readonly memory as it was before. Very interesting insight, thanks! Commented Sep 3, 2013 at 13:38
1

The keyword "const" is more a label for the programmer team like "private" and "public" not a compiler directive or compiler hint. A compiler can use it for optimization but don't need to. The compiler have only to control the abuse and prevent it. So the behavior you see is totally ok. And no, it is impossible that parts of one struct instance or class instance exist in different memory areas (do not count mapping in). Because that decision would impact the use of the struct and has to be allowed by the programmer.

3
  • "keyword "const" is more a label for the programmer team" - I am afraid, that in this case members of this team may have slightly different opinions on what this label means.
    – SChepurin
    Commented Sep 3, 2013 at 7:50
  • I mean that the good explanation would be - "The const qualifier is an instruction to the compiler to reject code that attempts to modify that object directly; attempts to modify the object indirectly ... results in undefined behavior, meaning any result is possible." (stackoverflow.com/questions/4275504/…)
    – SChepurin
    Commented Sep 3, 2013 at 8:33
  • You are right. My response was written in a haste. Nevertheless it is in my opinion more human readable. And yeah, working in different teams over the years, I am always surprised how people try to trick the compiler and expect to work that in a proper way. Commented Sep 3, 2013 at 8:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.