Const-правильность и аппаратная запись

Скажем, у меня есть следующая функция-член:

void CFoo::regWrite( int addr, int data )
{
reg_write( addr, data ); // driver call to e.g. write a firmware register
}

Ясно, что вызов этой функции не изменяет внутреннее состояние объекта, для которого она вызывается. Тем не менее, это меняет состояние любого этого Foo пример представляет собой.

При таких обстоятельствах следует Foo::regWrite(int addr, int data) быть константной функцией?

5

Решение

Вы должны решить, что означает «логически постоянный» для класса CFooи это зависит от того, для чего предназначен класс.

Если CFoo истолковывается как ссылаясь на некоторые данные, тогда может иметь смысл изменить эти данные с помощью const экземпляр CFoo, в этом случае ваша функция-член будет const, Для примеров этого рассмотрим другие типы, которые ссылаются на некоторые данные — вы можете изменить ссылку и char *const или const std::unique_ptr<char>,

Если CFoo истолковывается как владеть некоторыми данными, тогда может иметь смысл запретить модификацию через const экземпляр CFoo, В качестве примеров этого рассмотрим контейнеры, в которых элементы логически являются «частью состояния объекта», даже если они физически не являются частью объекта. Так vector::operator[] имеет постоянную перегрузку, которая возвращает const T& а не T&, insert функция-член неконстантна и т. д.

3

Другие решения

Программист должен определить, что «const» должно означать для класса. Со спецификатором mutable Вы даже можете иметь constобъект с изменяющимися значениями в элементе. Когда дело доходит до аппаратного обеспечения, можно рассматривать конфигурацию как цель для правильности констант: пока конфигурация не изменяется, объект можно считать постоянным.

1

Аналогичная проблема возникает, если у вас есть указатели на другие объекты в вашем классе: ваш метод const может затем вызывать неконстантные методы для другого объекта и, таким образом, модифицировать его.

Если вы посмотрите на аппаратное обеспечение как на какой-то другой объект, на который ссылается ваш класс, было бы совершенно правильно изменить настройки прошивки (поскольку изменяется только объект, на который ссылается). Если вы хотите, чтобы ваш класс «представлял» аппаратное обеспечение (или его часть), я бы предпочел не отмечать метод как const,

Поэтому я думаю, что это в основном зависит от того, как вы разработали свой класс.

1

Есть два способа взглянуть на это — угол оптимизации и логика этого объявления. Что важнее, решать вам.

оптимизация

РЕДАКТИРОВАТЬЯ сделал несколько неверных предположений. Похоже, что компилятор на самом деле не свободен для выполнения приведенных ниже оптимизаций, а сделает их только путем анализа тело метода, чтобы гарантировать, что никакие модификации не происходят (и даже тогда только в простых случаях).

Имея это const позволит компилятору немного оптимизировать
Больше. Это знает что regWrite не меняет поля в
объект, так что он может хранить их, если он хранит их в регистрах, и
делать аналогичные оптимизации, которые опираются на объекты поля Не существует
изменилось.

Это действительно единственное, от чего будет зависеть компилятор
сделать такое определение, так что имея это const в порядке и может
Теоретически разрешить лучшую производительность.

Логический смысл

Это не интуитивно, чтобы иметь const метод, целью которого является деструктивное изменение. Обычная интуиция программиста заключается в том, что пока я вызываю только методы const, результаты других const методы не должны меняться. Если вы нарушаете этот неписаный контракт, ожидайте, что люди будут удивлены — даже если с компилятором все в порядке.

Я не уверен, будет ли это здесь нарушено — это будет зависеть от другого кода в этом классе. Однако, если не важны другие соображения (производительность и т. Д.), const является (для меня) главным образом маркером на интерфейсе, который говорит, что «вызов этого не меняет состояние этого объекта», для широкого определения «состояния».

Однако это мрачное основание, и от вас зависит, что вы считаете изменением состояния. Если вы думаете, что ваш объект прошивки представляет ссылка на сайт для внутренних органов, написание реестра ничего не меняет в этом ссылка на сайт и является постоянным Если вы думаете, что это представляет состояние базовых регистров, то запись в регистры — это изменение состояния.

1