Подтвердить что ты не робот

С++ - Что такое летучие представления при применении к методу?

Если у меня есть объявление метода С++, как показано ниже:

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Вероятно, вы знакомы с методами const и const-correctness (см. "Пункт 15 - Использовать const proactively" в Стандарты кодирования С++ by Sutter and Alexandrescu), а 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-correctness предотвращает непреднамеренные ошибки во время компиляции, а также делает код "более понятным, отслеживаемым и обоснованным" (Sutter and Alexandrescu). Летучесть-правильность может работать аналогично, но гораздо менее используется (обратите внимание, что const_cast в С++ может отбрасывать const, volatile или const volatile, но вместо вызова cv_cast или аналогичного, он назван в честь const, потому что он гораздо чаще используется для отбрасывания только const).

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


Update:

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

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

Ответ 3

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

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

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

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

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