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.
mutable is particularly useful if most of the members should be constant but a few need to be updatable. Data members declared as mutable can be modified even though they are the part of object declared as const. You cannot use the mutable specifier with names declared as static or const, or reference.
Mutable data members are those members whose values can be changed in runtime even if the object is of constant type. It is just opposite to constant. Sometimes logic required to use only one or two data member as a variable and another one as a constant to handle the data.
Mutex and mutable go together (M&M rule, C++11) A mutable member variable is presumed to be a shared variable so it should be synchronized with a mutex (or made atomic) If a member variable is itself a mutex, it should be mutable. This is required to use it inside a const member function.
mutable : The mutable keyword overrides any enclosing const statement. A mutable member of a const object can be modified. volatile : The volatile keyword is an implementation-dependent modifier, used when declaring variables, which prevents the compiler from optimizing those variables.
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 themutable
class member even though the rest of the object isconst
.[...]
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 aconst
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With