Функции нестабильных членов С++
class MyClass
{
int x, y;
void foo() volatile {
// do stuff with x
// do stuff with y
}
};
Должен ли я объявлять 'x' и 'y' как volatile или будут ли все переменные-члены обрабатываться автоматически как volatile?
Я хочу убедиться, что "материал с" х "не переупорядочивается с помощью" stuff with "y" компилятором.
EDIT:
Что произойдет, если я перевешу нормальный тип на летучий тип? Означает ли это, что компилятор не переупорядочивает доступ к этому местоположению? Я хочу передать нормальную переменную в особой ситуации функции, параметр которой нестабилен. Я должен быть уверен, что компилятор не переупорядочивает этот вызов с помощью предыдущих или последующих чтений и записей.
Ответы
Ответ 1
Маркировка функции-члена volatile
похожа на ее маркировку const
; это означает, что объект получателя обрабатывается так, как если бы он был объявлен как volatile T*
. Соответственно, любая ссылка на x
или y
будет рассматриваться как volatile
, прочитанная в функции-члене. Более того, объект volatile
может вызывать только функции-члены volatile
.
Тем не менее, вы можете пометить x
и y
volatile
в любом случае, если вы действительно хотите, чтобы все обращения к ним обрабатывались как volatile
.
Ответ 2
Вы не должны явно объявлять переменные-члены.
Из стандартных документов 9.3.2.3,
Аналогично, изменчивая семантика (7.1.6.1) применяется в энергозависимых функциях-членах при доступе к объекту и его нестатической данных.
Ответ 3
Следующий код:
#include <iostream>
class Bar
{
public:
void test();
};
class Foo
{
public:
void test() volatile { x.test(); }
private:
Bar x;
};
int main()
{
Foo foo;
foo.test();
return 0;
}
Вызывает ошибку при компиляции с помощью gcc:
main.cpp: In member function 'void Foo::test() volatile':
main.cpp:14:33: error: no matching function for call to 'Bar::test() volatile'
main.cpp:7:8: note: candidate is: void Bar::test() <near match>
И поскольку экземпляр volatile
не может вызывать метод non-volatile
, мы можем предположить, что в методе да, x
и y
будет volatile
, даже если экземпляр MyClass
не объявлен volatile
.
Примечание: вы можете удалить квалификатор volatile
, используя const_cast<>
, если вам когда-либо понадобится; однако, будьте осторожны, потому что, как и в случае с const
, это может привести к поведению undefined в некоторых случаях.
Ответ 4
IBM подразумевает, он работает точно так же, как функции const.
Ответ 5
Итак, используя оригинальный пример:
class MyClass
{
int x, y;
void foo() volatile {
// do stuff with x
// do stuff with y
// with no "non-volatile" optimization of the stuff done with x, y (or anything else)
}
void foo() {
// do stuff with x
// do stuff with y
// the stuff done with x, y (and anything else) may be optimized
}
};