C ++ - Что представляет собой volatile при применении к методу? - PullRequest
19 голосов
/ 24 февраля 2011

Если у меня есть объявление метода C ++ следующим образом:

class A
{
public:
   double getPrice() volatile;
};
  1. Что означает volatile здесь?
  2. Для чего его можно использовать?

Вас может заинтересовать эта статья доктора Доббса, написанная Андреем Александреску.Я был:)

Редактировать: Эта статья была написана некоторое время назад, и теперь кажется, что сообщество движется дальше.У Херба Саттера есть это, чтобы сказать это .Спасибо Iain (и Herb!)

mlimber указывает, что у Андрея была статья-продолжение здесь , где он продолжает выступать за использование изменчивой корректности в качестве ценного инструмента для определения условий гонки.в системах, поддерживающих POSIX-подобные мьютексы.

Ответы [ 3 ]

10 голосов
/ 24 февраля 2011

Вы, вероятно, знакомы с const методами и правильностью const (см. "Пункт 15 - Использование const проактивно" в C ++ Стандарты кодирования Саттера и Александреску),и volatile работает аналогичным, но немного отличающимся образом, чтобы дать то, что можно было бы назвать «изменчивой корректностью».

Как и const, volatile является модификатором типа.При присоединении к функции-члену, как в вашем примере, либо модификатор (или оба!) Означают, что объект, для которого вызывается метод, должен иметь или быть преобразованным к этому типу.

Учтите:

struct A
{
  void f();
  void cf() const;
  void vf() volatile;
  void cvf() const volatile;
  // ...
};

void foo( A& a, const A& ca, volatile A& va, const volatile A& cva )
{
  a.f();    // Ok
  a.cf();   // Ok: Can convert non-const    obj to const    obj
  a.vf();   // Ok: Can convert non-volatile obj to volatile obj
  a.cvf();  // Ok: Can convert non-cv       obj to cv       obj

  ca.f();   // Error: can't call non-const method on const obj
  ca.cf();  // Ok
  ca.vf();  // Error: can't call non-const method on const obj
  ca.cvf(); // Ok: Can convert

  va.f();   // Error: can't call non-volatile method on volatile obj
  va.cf();  // Error: can't call non-volatile method on volatile obj
  va.vf();  // Ok
  va.cvf(); // Ok: Can convert

  cva.f();   // Error: can't call non-cv method on cv obj
  cva.cf();  // Error: can't call non-cv method on cv obj
  cva.vf();  // Error: can't call non-cv method on cv obj
  cva.cvf(); // Ok
}

Обратите внимание, что это ошибки во время компиляции, а не ошибки во время выполнения, и именно здесь возникает его потенциальная полезность.

Const -корректность предотвращает непреднамеренные ошибки во время компиляции а также делает код «проще для понимания, отслеживания и анализа» (Саттер и Александреску).Volatile-корректность может функционировать аналогично, но используется гораздо реже (обратите внимание, что const_cast в C ++ может отбрасывать const, volatile или const volatile, но вместо того, чтобы называть его cv_cast или подобным, он назван в честь const, потому что он гораздо чаще используется для отбрасывания всего лишь const).

Например, в "volatile - лучший друг многопоточного программиста" , Андрей Александреску приводит несколько примеровкак это можно использовать, чтобы компилятор автоматически определял условия гонки в многопоточном коде.В нем также есть много объяснений о том, как работают модификаторы типов, но см. Также его последующие комментарии в его последующем столбце .


Обновление :

Обратите внимание, что C ++ 11 меняет значение const. Так говорит Саттер : «const теперь действительно означает« только для чтения »или« безопасно читать одновременно »- либо физически / побитово const, либо внутренне синхронизировано, так что любые фактические записи синхронизируютсяс любым возможным одновременным доступом const, чтобы вызывающие абоненты не могли заметить разницу. "

В другом месте он отмечает , что, хотя C ++ 11 добавил примитивы параллелизма, volatileвсе еще не один из них: «Изменчивые переменные C ++ (которые не имеют аналогов в таких языках, как C # и Java) всегда выходят за рамки этой и любой другой статьи о модели памяти и синхронизации. Это потому, что переменные C ++ не относятся к потокамили общение вообще и не взаимодействовать с этими вещами. Скорее, энергозависимую переменную C ++ следует рассматривать как портал в другую вселенную за пределами языка - область памяти, которая по определению не подчиняется модели памяти языка, поскольку эта область памятидоступ к аппаратным средствам (например, записанный на дауghter card), имеют более одного адреса или являются «странными» иными словами.Таким образом, изменчивые переменные C ++ являются универсальным исключением из любого руководства по синхронизации, потому что они всегда неотъемлемы и являются «нестабильными» и несинхронизируемыми с использованием обычных инструментов (мьютексов, атомик и т. Д.) И, в более общем смысле, существуют вне всех нормалей языка и компилятора, включая то, что они обычноне может быть оптимизирован компилятором .... Подробнее см. мою статью ' volatile против volatile .' "

8 голосов
/ 24 февраля 2011

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

Какая польза?Ну, глобально изменчивый бесполезен (его часто неправильно понимают как применимый для программирования MT, это не так в C ++, см., Например, http://www.drdobbs.com/high-performance-computing/212701484),, а объекты изменчивого класса еще менее полезны.

IIRC А. Александреску предложил использовать проверку типов, выполняемую для энергозависимых объектов, чтобы статически обеспечить некоторые свойства, полезные для программирования MT (скажем, блокировка была взята до вызова функции-члена). К сожалению, я не нахожустатья назад. (Вот это: http://www.drdobbs.com/184403766)

Редактировать: добавлены ссылки из комментариев (они были добавлены также в вопросе).

3 голосов
/ 24 февраля 2011

В функциях-членах (единственных функциях, которые могут иметь cv-квалификаторы), const или volatile эффективно изменяет указатель this.Следовательно, подобно функции-члену const доступ к объекту возможен только так, как если бы он был через указатель const, функция-член volatile может получить доступ к объекту только так, как если бы он был volatile

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

Это означает, что любые операции, связанные с объектом в volatile функциях-членах, должны выполняться в том порядке, в котором они записаны.

Кроме того, volatile функция-член может вызывать только другие volatile(или const volatile) функции-члены.

Что касается того, для чего это нужно ... честно говоря, сейчас я не могу придумать хорошее применение.volatile жизненно важен для некоторых объектов данных, таких как указатели, указывающие на регистры ввода / вывода, но я не могу понять, почему функция-член volatile была бы полезна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...