Question

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.

Was it helpful?

Solution 2

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.

OTHER TIPS

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.

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.

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