Отключает ли изменяемый элемент оптимизации const для не изменяемых элементов?

Насколько я знаю, в 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 ++ стандартное расположение памяти?

Это было протестировано с использованием Visual Studio 2010 в Windows 7 и GCC 4.7.2 в Ubuntu.

5

Решение

Чтобы объяснить, почему компилятор должен делать «все или ничего», когда речь идет о том, где хранить struct: В большинстве процессоров страницы памяти имеют размер 4 КБ (на некоторых страницах по 8 КБ). Это гранулярность блоков «только чтение» и «чтение / запись». Таким образом, вы не можете иметь одно 4-байтовое целое число в памяти только для чтения, а затем следующие 4-байтовые целые числа в памяти чтения-записи (если они точно не пересекают границу памяти 4 КБ), но это определенно приведет к довольно расточительному использованию памяти, если у вас есть массив из 3000, занимающий 12 МБ).

Обратите внимание, что это не «оптимизация». Память только для чтения не быстрее, чем память для чтения и записи. Это защита от глупости пользователей const и запись в данные, которые они не должны писать.

Кроме того, если вы добавите конструктор, который «делает что-то» на ваш structон, скорее всего, будет хранить структуру в памяти для чтения и записи, потому что компилятору довольно сложно генерировать код для включения и выключения только для чтения во время выполнения.

4

Другие решения

Стандарт говорит о mutable участники во многих местах. Я цитирую ниже три части стандарта, поясняя, что вы можете изменять только mutable члены const объект. В противном случае это Неопределенное поведение.

3.9.3 CV-квалификаторы [basic.type.qualifier]

константный объект является объектом типа const T или неизменяемый подобъект такого объекта.

[…]

7.1.1 Спецификаторы класса хранения [dcl.stc]

mutable спецификатор члена данных класса обнуляет спецификатор const, примененный к содержащему объекту класса, и разрешает модификацию mutable член класса, хотя остальная часть объекта const,

[…]

7.1.6.1 Спецификаторы cv [dcl.type.cv]

За исключением того, что любой член класса объявлен mutable (7.1.1) могут быть изменены, любая попытка изменить const объект в течение его жизни (3.8) приводит к неопределенное поведение.


Можно ли хранить части struct в только для чтения памяти и других частей не только для чтения памяти и соблюдение C ++ стандартное расположение памяти?

Нет, невозможно хранить части struct (или же class) в другой области памяти, чем остальная часть объекта.

5

Ключевое слово «const» — это скорее метка для команды программистов, например «private» и «public», а не директива компилятора или подсказка компилятора. Компилятор может использовать его для оптимизации, но это не нужно. Компилятор должен только контролировать злоупотребления и предотвращать их. Таким образом, поведение, которое вы видите, совершенно нормально.
И нет, невозможно, чтобы части одного экземпляра структуры или экземпляра класса существовали в разных областях памяти (не считая отображение). Потому что это решение повлияет на использование структуры и должно быть разрешено программистом.

1
По вопросам рекламы [email protected]