Вы запросили практический пример функций энергозависимых членов. Ну, я не могу думать об этом, потому что единственные ситуации, которые я мог бы представить, были настолько низкоуровневыми, что я не стал бы рассматривать использование функции-члена в первую очередь, а просто простую структуру с доступом к данным-членам по летучей ссылке.
Однако давайте добавим в него постоянную изменчивую функцию только для того, чтобы ответить на вопрос. Предположим, у вас есть порт с адресом 0x378h, который содержит 2 целых числа по 4 байта. Тогда вы могли бы написать
struct ints {
int first;
int second;
int getfirst() const volatile {
return first;
}
int getsecond() const volatile {
return second;
}
// note that you could also overload on volatile-ness, just like
// with const-ness
};
// could also be mapped by the linker.
ints const volatile &p = *reinterpret_cast<ints*>(0x378L);
Вы заявляете
Я не изменяю их, но другая вещь вне этой абстрактной семантики может изменить это. Поэтому всегда делайте реальную загрузку со своего адреса.
На самом деле, volatile сигнализирует о том, что значением объекта может быть не то значение, которое в последний раз было сохранено в нем, а фактически неизвестное и могло быть изменено между внешними (не наблюдаемыми компилятором) условиями. Поэтому, когда вы читаете из изменчивого объекта, компилятор должен эмулировать точную абстрактную семантику и не выполнять оптимизацию:
a = 4;
a *= 2;
// can't be optimized to a = 8; if a is volatile because the abstract
// semantics described by the language contain two assignments and one load.
Следующее уже определяет, что делает volatile
. Все можно найти в 1.9
стандарта. Параметры, о которых он говорит, это вещи, определяемые реализацией, например, sizeof некоторого типа.
Семантические описания в этом международном стандарте определяют параметризованную недетерминированную абстрактную машину. Настоящий международный стандарт не предъявляет требований к структуре соответствующих реализаций. В частности, им не нужно копировать или эмулировать структуру абстрактной машины. Скорее, соответствующие реализации требуются для эмуляции (только) наблюдаемого поведения абстрактной машины, как объяснено ниже. [...]
Соответствующая реализация, выполняющая правильно сформированную программу, должна производить то же наблюдаемое поведение, что и одна из возможных последовательностей выполнения соответствующего экземпляра абстрактной машины с той же программой и тем же вводом. [...]
Наблюдаемое поведение абстрактной машины - это последовательность операций чтения и записи в изменчивые данные и вызовов функций ввода-вывода библиотеки.