据我所知,在C ++ struct / class中,具有相同访问控制的成员以声明顺序存储在内存中。下一个示例m
和c
应该一个接一个地存储:
#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;
}
在此示例中,程序运行并打印2个随机数。如果我删除mutable
它会崩溃,因为cx
存储在只读保护的内存中。
这让我很奇怪 - 一个mutable
成员是否对整个const
禁用struct
优化(以某种方式让所有成员mutable
)?
是否可以将struct
的部分存储在只读存储器中,将其他部分存储在非只读存储器中并尊重C ++标准存储器布局?
这是在Windows 7上使用Visual Studio 2010和在Ubuntu上使用GCC 4.7.2进行测试的。
答案 0 :(得分:5)
该标准涉及许多地方的mutable
成员。我在下面引用标准的三个部分,解释您只能修改mutable
对象的const
成员。否则它是未定义的行为。
3.9.3 CV-qualifiers [basic.type.qualifier]
const对象是
const T
类型的对象或此类对象的不可变子对象。<强> [...] 强>
7.1.1存储类说明符[dcl.stc]
类数据成员上的
mutable
说明符使应用于包含类对象的const说明符无效,并允许修改mutable
类成员,即使该对象的其余部分为const
<强> [...] 强>
7.1.6.1 cv-qualifiers [dcl.type.cv]
除了可以修改声明为
mutable
(7.1.1)的任何类成员之外,任何在其生命周期内修改const
对象的尝试(3.8)都会导致未定义的行为。
是否可以将
struct
的部分存储在只读存储器中,将其他部分存储在非只读存储器中并尊重C ++标准存储器布局?
不,不可能将struct
(或class
)的部分存储在与对象其余部分不同的内存区域中。
答案 1 :(得分:4)
解释为什么编译器在存储struct
的位置时必须“全有或全无”:在大多数处理器中,内存页面是4KB(少数有8KB页面)。这是“只读”与“读/写”内存块的粒度。所以你不能在只读存储器中有一个4字节的整数,然后读写存储器中的下一个4字节整数(除非它们正好跨越4KB的存储器边界 - 但这肯定会造成非常浪费的使用内存,如果你有一个3000的数组,占用12MB)。
请注意,这不是“优化”。只读存储器并不比读写存储器快。它可以防止用户对const
感到愚蠢,并写入他们不应该写入的数据。
此外,如果你向你的struct
添加一个“做某事”的构造函数,它很可能将结构存储在读写内存中,因为编译器生成代码以切换只读是非常棘手的在运行时打开和关闭。
答案 2 :(得分:1)
关键字“const”更像是程序员团队的标签,如“private”和“public”,而不是编译器指令或编译器提示。编译器可以使用它进行优化,但不需要。编译器只需控制滥用并阻止它。所以你看到的行为完全没问题。 不,不可能一个结构实例或类实例的部分存在于不同的内存区域(不计入映射)。因为该决定会影响结构的使用,并且程序员必须允许。