可变成员是否对非可变成员禁用const优化?

时间:2013-09-03 07:10:20

标签: c++ const mutable

据我所知,在C ++ struct / class中,具有相同访问控制的成员以声明顺序存储在内存中。下一个示例mc应该一个接一个地存储:

#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进行测试的。

3 个答案:

答案 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”,而不是编译器指令或编译器提示。编译器可以使用它进行优化,但不需要。编译器只需控制滥用并阻止它。所以你看到的行为完全没问题。 不,不可能一个结构实例或类实例的部分存在于不同的内存区域(不计入映射)。因为该决定会影响结构的使用,并且程序员必须允许。