8.1 Когда происходит обращение к volatile-объекту C++?
Стандарт C++ отличается от стандарта C трактовкой volatile-объектов. В нём не указано, что считается обращением к volatile-объекту, — сказано лишь, что, когда это возможно, C++ должен вести себя с volatile-объектами аналогично C. Однако различия в том, какие выражения являются l-значениями в C и C++, усложняют такое поведение. При обращении к volatile-объектам G++ ведёт себя так же, как GCC. См. Volatiles с описанием поведения GCC.
Спецификации языков C и C++ различаются в том, как трактуется обращение к объекту в контексте void:
volatile int *src = somevalue; *src;
Стандарт C++ устанавливает, что такие выражения не подвергаются преобразованию l-значения в r-значение и что тип разыменованного объекта может быть неполным. Стандарт C++ явно не указывает, что именно преобразование l-значения в r-значение вызывает обращение к объекту. Есть основания полагать, что это так, поскольку в противном случае некоторые простые выражения становились бы неопределёнными. Однако, поскольку это удивило бы большинство программистов, при разыменовании указателя на volatile-объект полного типа G++ ведёт себя так же, как GCC для эквивалентного типа в C. Если тип объекта неполный, G++ выдаёт предупреждение; чтобы принудительно вызвать ошибку, необходимо принудительно выполнить преобразование в r-значение, например с помощью статического приведения типа.
При использовании ссылки на volatile G++ не считает эквивалентные выражения обращениями к volatile-объектам, а вместо этого выдаёт предупреждение о том, что обращение к volatile-объекту не происходит. Причина в том, что иначе было бы трудно определить, где именно происходит обращение к volatile-объекту, и невозможно было бы игнорировать возвращаемое значение функций, возвращающих ссылки на volatile-объекты. И снова: чтобы принудительно выполнить чтение, приведите ссылку к r-значению.
При присваивании volatile-объекту G++ реализует то же поведение, что и GCC: присвоенный объект не считывается повторно, вместо этого используется присвоенное r-значение. Обратите внимание, что в C++ выражения присваивания являются l-значениями, и при использовании в качестве l-значения они ссылаются на 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-15.3.0/gcc/C_002b_002b-Volatiles.html