Переменные константы помещаются в постоянное запоминающее устройство?
Или есть ли другая защита от их изменения?
Имеет смысл, если они находятся в постоянной памяти - что причина для их создания const
, правильно?
Ответы
Ответ 1
const
- это конструкция времени компиляции и не известна во время выполнения. Это только поможет помочь программисту в его программе и предотвратить появление ошибок, изменив вещи, которые не должны были быть изменены. const
сообщает компилятору, что вы не хотите, чтобы эта переменная была изменена, и поэтому компилятор будет ее применять.
Ответ 2
Нет, они не обязаны быть. const
- время компиляции и позволяет компилятору выполнять некоторую оптимизацию. Однако необязательно, чтобы переменная была помещена в ячейку памяти только для чтения.
См. этот пример: Undefined Поведение (благодаря Dyp для указания этого):
#include <iostream>
int main()
{
const int bla = 42;
int *ptr = const_cast<int *>(&bla);
std::cout << *ptr << std::endl;
*ptr = 21;
std::cout << *ptr << std::endl;
}
Он выведет 42
и 21
, но также может потерпеть крах.
Теперь посмотрим на это:
#include <iostream>
int main()
{
const int bla = 42;
int *ptr = const_cast<int *>(&bla);
std::cout << bla << std::endl;
*ptr = 21;
std::cout << bla << std::endl;
}
В моем компиляторе этот вывод 42
и 42
, потому что компилятор сделал некоторые оптимизации. Обратите внимание, что он все равно может быть поврежден из-за *ptr = 21
;
Ответ 3
Существует множество случаев, когда компилятор не может сделать const
доступным только для чтения (при условии, что в системе в первую очередь имеется постоянная память). Фактически, я считаю, что почти все компиляторы, как правило, заставляют объекты const
жить в обычной памяти данных (или стека), как обычные переменные.
Основной целью const
является объявление вашего намерения с компилятором, которого вы не хотите, и не должны изменять какое-либо значение. Я не вижу причин, по которым компиляторы не могут при ограниченных обстоятельствах помещать переменные const
в постоянную память. Но я также не стал бы полагаться на это - стандарт, безусловно, делает это возможным, поскольку в нем упоминается, что с помощью const_cast
удалить const
из объекта, который был первоначально отмечен const
, а затем записать в него поведение undefined (поэтому компилятор не должен позволять изменять значение после использования const_cast
для удаления оригинала const
- и, таким образом, разрешает "Сбой, потому что мы пытались записать в постоянную память" ).
Но рассмотрим следующее:
class X
{
int x;
public:
X(int v) : x(v) {}
}
int c = rand();
const X a(c+1);
const X b(c+2);
В этом случае компилятор не может знать значение в c
, которое он получил из rand
, поэтому он не может инициализировать a
и b
во время компиляции.
Ответ 4
Что касается стандарта, то нет необходимости размещать переменные const
в ОЗУ с защитой от записи. const
- это в основном только документация, связанная с компилятором.
Практически, если значение может быть вычислено полностью во время компиляции, компиляторы обычно используют хранилище только для чтения для переменной const
. В противном случае они помещаются в одни и те же кучи для чтения и записи, как и все остальные.
Ответ 5
Нет. Рассмотрим объект const
с членом mutable
. Как упоминалось, const представляет собой конструкцию времени компиляции, чтобы помочь программисту передать намерение.
Ответ 6
Ключевое слово const
имеет два значения:
- Известный "Я обещаю не изменять это состояние объекта"
- В качестве специального правила компилятор может размещать объекты, определение которых
const
в постоянной памяти, пока объект не имеет элементов mutable
(т.е. весь объект является состоянием объекта).
Вот почему const_cast
разрешено отбрасывать спецификатор const, но требование состоит в том, что само определение объекта не является const
. Wikipedia on const correctness гласит: "Однако любая попытка изменить объект, который сам объявляет const с помощью const_cast, приводит к поведению undefined в соответствии с к стандарту ISO С++.".
Ответ 7
Не только стандарт С++ не гарантирует, что объекты const
находятся в постоянной памяти, реализовать реализацию будет трудно, как описано ниже.
Было бы сложно реализовать С++ для размещения объектов const
с автоматической продолжительностью хранения, адреса которых берутся в постоянной памяти. Это связано с тем, что каждый другой объект должен иметь другой адрес (потому что их указатели должны сравнивать неравные). Поэтому каждый такой объект должен быть создан каждый раз, когда выполняется его блок.
Если адрес объекта const
не принят, компилятор может реализовать несколько экземпляров его (в вычислительной модели С++), используя только один экземпляр в памяти (поскольку каждый экземпляр идентичен и не изменяется). Таким образом, такой объект может быть создан один раз при запуске программы (вероятно, при загрузке из секции с постоянными данными в файле программы), помеченном только для чтения и оставлен без изменений в течение всего времени выполнения программы. Однако, если адрес объекта принимается (и используется видимыми способами), то компилятор должен создать каждый отдельный экземпляр объекта (или как-то "поддельный", который имеет один экземпляр с несколькими адресами). В общем, компилятор не может предсказать, сколько одновременных исполнений блока может существовать одновременно (например, когда есть рекурсивные вызовы функций). Поэтому при запуске программы он не может создать все экземпляры требуемого объекта. Они должны быть созданы на лету.
Создание объектов требует изменения памяти, для записи начальных значений объектов. Таким образом, размещение объектов const
с автоматическим временем хранения в постоянной памяти потребует частое изменение памяти из режима "только для чтения" для записи и возврата. Чтобы создать новый объект, программе необходимо будет изменить постоянное запоминающее устройство на записываемую память, записать начальное значение нового объекта и изменить память обратно в режим "только для чтения".
Кроме того, это обеспечило бы появление памяти только для чтения только для однопоточных программ без обработчиков сигналов. Программы с несколькими потоками выполнения или отдельными обработчиками могут наблюдать память, пока она находится в состоянии записи.
Ответ 8
Если они были в памяти только для чтения, это помешало бы const_cast
быть полезным и значимым, поэтому такой код невозможен, передавая переменную const
функции с параметром const
: -
void print (char * str)
{
cout << str << endl;
}
int main ()
{
const char * c = "test text";
print ( const_cast<char *> (c) );
return 0;
}
Обратите внимание, что функция печати может фактически изменить значение в первоначально определенной переменной const
c
.
Ответ 9
const
- это знак для компилятора. Во время компиляции компилятор добавляет константы в отдельную группу и проверяет попытки ее изменения. Если какая-то функция пытается это сделать, вы получите ошибку компилятора.
Однако можно комбинировать компилятор и изменять значение const
с помощью указателей и const_cast
, но в результате этого вы обманываете не компилятор, а самостоятельно (или коллега).
Как я уже сказал, моему другу, который смотрел, как изменить значение const
. const
предназначен не только для компилятора, но и для разработчика, а затем для компилятора, потому что он показывает, какие данные не будут изменены.