изменчивый и изменчивый в C ++


85

У меня вопрос о разнице между изменчивым и изменчивым. Я заметил, что оба значения означают, что это можно изменить. Что еще? Это одно и то же? Какая разница? Где они применимы? Почему предлагаются две идеи? Как их использовать по-другому?

Большое спасибо.

Ответы:


112

mutableПоле может быть изменено даже в объекте , доступном через constуказатель или ссылки, или в constобъекте, так что компилятор знает , чтобы не прятать его в памяти R / O. volatileРасположение один , который может быть изменен с помощью кода компилятор не знает о (например , каком - то драйвере уровня ядра), так что компилятор не знает , чтобы оптимизировать , например , зарегистрировать присвоение этого значения при недопустимом предположении , что значение «не может иметь изменено "с момента последней загрузки в этот регистр. Очень разная информация передается компилятору, чтобы остановить самые разные недопустимые оптимизации.


13
volatileобъекты также могут быть изменены процессами, вообще не задействующими ЦП. Например, регистр приема байтов в коммуникационном периферийном устройстве может увеличиваться на единицу при получении байта (и это может даже вызвать прерывание). Другой пример - регистр флагов ожидающих прерываний в периферийном устройстве.
Mike DeSimone

55
Кроме того, volatileэто не только означает, что объект может изменяться вне зависимости от компилятора - это также означает, что записи в объект не могут быть устранены компилятором, даже если эти записи кажутся бесполезными. Например: x = 1; x = 0; если xявляется изменчивым, компилятор должен выполнить обе операции записи (что может иметь значение на аппаратном уровне). Однако для энергонезависимого объекта компилятор может не беспокоиться о написании, 1поскольку он никогда не использовался.
Майкл Берр,

15
Объект может быть отмечен как, так constи volatile! Поменять предмет нельзя, но можно поменять за спиной.
CTMacUser

2
@Destructor: обычная ситуация для записи в регистр аппаратного устройства.
Майкл Берр

5
@Destructor, допустим, вы контролируете состояние светодиода. Запись 0 выключает его, запись 1 включает. Если мне нужно мигать светодиодом, чтобы сообщить о каком-либо статусе ошибки, но компилятор решает оптимизировать все записи, кроме последней, поскольку ни одно из значений не используется, тогда светодиод никогда не мигает, и желаемое поведение не реализуется .
iheanyi

28

mutable: Ключевое слово mutable переопределяет любой включающий оператор const. Изменяемый член константного объекта может быть изменен.

volatile: Ключевое слово volatile - это модификатор, зависящий от реализации, используемый при объявлении переменных, который не позволяет компилятору оптимизировать эти переменные. Volatile следует использовать с переменными, значение которых может изменяться неожиданным образом (например, из-за прерывания), что может конфликтовать с оптимизацией, которую может выполнить компилятор.

Источник


Вы сказали, что Volatile should be used with variables whose value can change in unexpected waysлучше использовать его в случайном порядке?
Асиф Муштак

@AsifMushtaq не ценности. способами. mutable влияет на разрешения написанного вами кода. Таким образом, вы можете получить доступ к переменной через ссылку const ptr или const. Что, если это не ваш код меняет его? Что-то компилятор не может проверить ptr или ссылочный тип? Это непостоянно. Кроме того, volatile заставляет кэш записывать обратно в основную память. Таким образом, это используется МНОГО с многопоточным кодом. :)
Дэн

22

Это определенно НЕ одно и то же. Mutable взаимодействует с const. Если у вас есть константный указатель, вы обычно не можете изменять члены. Mutable представляет собой исключение из этого правила.

Volatile, с другой стороны, совершенно не связано с изменениями, внесенными программой. Это означает, что память может измениться по причинам, не зависящим от компилятора, поэтому компилятор должен каждый раз читать или записывать адрес памяти и не может кэшировать содержимое в регистре.


«Volatile, с другой стороны, совершенно не связан с изменениями, сделанными программой ...» - хммм, сделайте член volatile и посмотрите, что ломается во время компиляции. Попытка добавить volatile постфактум очень похожа на попытку добавить const постфактум ... Мучительно.
jww

@jww: Это совершенно не связано с записями, сделанными программой. Вы можете взять адрес объекта типа T, сохранить его в const T*и прочитать из него. Если вы создадите этот объект volatile, сохранить его адрес в нем const T*не удастся, даже если вы никогда не пытаетесь писать. volatileа изменения / модификации / записи в память из программного кода полностью ортогональны.
Бен Фойгт

17

Грубый, но эффективный способ осмыслить разницу:

  • Компилятор знает, когда изменяемый объект изменяется.
  • Компилятор не может знать, когда изменяется изменчивый объект.

1
В этом ключе: volatilebytes_received, mutablereference_count.
Mike DeSimone

11

Отмеченная переменная mutableпозволяет изменять ее в объявленном методе const.

Отмеченная переменная volatileсообщает компилятору, что он должен читать / записывать переменную каждый раз, когда ваш код также сообщает об этом (т.е. он не может оптимизировать доступ к переменной).


4

Я хотел бы добавить, что volatile также очень полезен при работе с многопоточными приложениями, т.е. у вас есть основной поток (где живет main ()), и вы создаете рабочий поток, который будет продолжать вращаться, пока переменная app_running имеет значение true. main () контролирует, является ли app_running истинным или ложным, поэтому, если вы не добавите атрибут volatile к объявлению app_running, если компилятор оптимизирует доступ к app_running в коде, выполняемом вторичным потоком, main ( ) может изменить "app_running" на false, но вторичный поток продолжит работу, потому что значение было кэшировано. Я видел такое же поведение при использовании gcc в Linux и VisualC ++. Атрибут "volatile", помещенный в объявление "app_running", решил проблему. Так,


1
Нет! Это распространенное заблуждение. C ++ 11 и C11 представили атомики для этой цели stackoverflow.com/questions/8819095/…
KristianR
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.