7.1 Когда обращается к объекту volatile C++? ¶
Стандарт C++ отличается от стандарта C в обращении с объектами volatile. Он не определяет, что представляет собой обращение к volatile, кроме утверждения, что C++ должен вести себя аналогично C в отношении volatile, где это возможно. Однако различие в свойствах выражений lvalue между C и C++ усложняет поведение. G++ ведет себя так же, как GCC в отношении доступа к volatile, см. Volatile для описания поведения GCC.
Спецификации языков C и C++ различаются при обращении к объекту в контексте void:
volatile int *src = somevalue; *src;
Стандарт C++ определяет, что такие выражения не подвергаются преобразованию lvalue в rvalue, и что тип обращённого к объекту может быть неполным. Стандарт C++ не указывает явно, что преобразование lvalue в rvalue является причиной обращения. Есть основания полагать, что это так, иначе некоторые простые выражения станут неопределёнными. Однако, чтобы не удивить большинству программистов, G++ обрабатывает обращение к указателю на volatile объект полного типа так же, как GCC обрабатывает эквивалентный тип в C. Когда у объекта неполный тип, G++ выводит предупреждение; если вы хотите получить ошибку, вы должны принудительно преобразовать в rvalue, например, с помощью статического преобразования.
При использовании ссылки на volatile, G++ не обрабатывает эквивалентные выражения как обращения к volatile, а вместо этого выводит предупреждение о том, что volatile не обращается. Основание для этого в том, что в противном случае становится трудно определить, где происходит доступ к volatile, и невозможно игнорировать возвращаемое значение из функций, возвращающих ссылки на volatile. Опять же, если вы хотите принудительно произвести чтение, преобразуйте ссылку в rvalue.
G++ реализует такое же поведение, как GCC, при присваивании объекту volatile — нет повторного чтения присвоенного объекта, повторно используется присвоенное rvalue. Обратите внимание, что в выражениях присваивания C++ — это lvalues, и если они используются в качестве lvalue, к объекту volatile обращаются. Например, vref ссылается на vobj, как ожидалось, в следующем примере:
volatile int vobj; volatile int &vref = vobj = something;
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/C_002b_002b-Volatiles.html