мінливий у порівнянні зі змінним у C ++


85

У мене питання про різницю між летким і змінним. Я помітив, що обидва ці два засоби означають, що їх можна змінити. Що ще? Це одне й те саме? Яка різниця? Де вони застосовуються? Чому пропонуються дві ідеї? Як використовувати їх по-різному?

Дуже дякую.

Відповіді:


112

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


13
volatileОб'єкти також можуть бути змінені процесами, які взагалі не залучають центральний процесор. Наприклад, отриманий байт регістр у периферійному пристрої зв'язку може збільшуватися при отриманні байта (і це може навіть викликати переривання). Інший приклад - реєстр прапорців, що очікують на переривання, у периферійному пристрої.
Mike DeSimone

55
Крім того, volatileце не означає лише те, що об'єкт може змінюватися поза межами відомостей компілятора - це також означає, що компілятор не може усунути записи в об'єкт, навіть якщо ці записи видаються марними. Наприклад: x = 1; x = 0; якщо xмінливий, компілятор повинен виконати обидві операції запису (що може бути значним на апаратному рівні). Однак для енергонезалежного об'єкта компілятор міг вирішити не турбуватись написанням, 1оскільки він ніколи не використовується.
Michael Burr

15
Об'єкт може бути позначений як constі volatile! Ви не можете змінити предмет, але його можна змінити за спиною.
CTMacUser

2
@Destructor: звичайна ситуація полягає у записі в реєстр апаратних пристроїв.
Michael Burr

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

28

mutable: Змінюване ключове слово замінює будь-яке вкладене твердження const. Змінюваний член об'єкта const може бути змінений.

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

Джерело


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

@AsifMushtaq не значення. шляхи. змінні ефекти дозволяють код, який ви пишете. Таким чином, ви можете отримати доступ до змінної через const ptr або const reference. Що робити, якщо це не ваш код, який його змінює? Щось компілятор не може перевірити ptr або тип посилання? Це нестабільно. А мінливий також змушує кеш-пам'ять повертати в основну пам'ять. Отже, це використовується LOT з багатопотоковим кодом. :)
Дан,

22

Вони точно НЕ одне і те ж. Змінний взаємодіє з const. Якщо у вас є вказівник const, ви, як правило, не можете змінити членів. Mutable забезпечує виняток із цього правила.

З іншого боку, нестабільність абсолютно не пов’язана зі змінами, внесеними програмою. Це означає, що пам'ять може змінюватися з причин, що не залежать від компілятора, тому компілятору доводиться щоразу читати або писати адресу пам'яті і не може кешувати вміст у реєстрі.


"Волатильність, з іншого боку, абсолютно не пов'язана зі змінами, внесеними програмою ..." - ммм, зробіть учасника нестабільним і подивіться, що ламається під час компіляції. Спроба додати мінливого після факту дуже схожа на спробу додати const після факту ... Болісно.
jww

@jww: Це абсолютно не пов'язано із написанням програми. Ви можете взяти адресу об'єкта типу T, зберегти його в const T*і читати з нього. Якщо ви зробите цей об’єкт volatile, збереження його адреси const T*не вдасться, хоча ви ніколи не намагаєтеся написати. volatileа зміни / модифікації / записи в пам'ять із програмного коду повністю ортогональні.
Бен Войгт,

17

Грубим, але ефективним способом мислення різниці є:

  • Компілятор знає, коли змінюється змінний об'єкт.
  • Компілятор не може знати, коли мінливий об'єкт змінюється.

1
У цьому ключі: volatileбайт_отримано, mutableпосилання_рахунок.
Mike DeSimone

11

Помічена змінна mutableдозволяє її модифікувати в оголошеному методі const.

Помічена змінна volatileповідомляє компілятору, що він повинен читати / писати змінну кожного разу, коли ваш код теж це повідомляє (тобто вона не може оптимізувати віддалений доступ до змінної).


4

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


1
Немає! Це загальне непорозуміння. C ++ 11 і С11 введені Atomics для цієї мети stackoverflow.com/questions/8819095 / ...
KristianR
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.