Правило 7-1-1 (обязательное) Неизменяемая переменная должна быть квалифицирована как const
Если переменную не нужно изменять, она должна быть объявлена с квалификацией const, чтобы ее нельзя было изменить. Тогда непараметрическая переменная потребует своей инициализации в точке объявления. Кроме того, будущее обслуживание не может случайно изменить значение.
void b ( int32_t * ); int32_t f ( int32_t * p1, // Non-compliant int32_t * const p2, // Compliant int32_t * const p3 ) // Compliant { *p1 = 10; *p2 = 10; b( p3 ); int32_t i = 0; // Non-compliant return i; }
Пример, включенный в стандарт, ориентирован на указатели. Правило требует, чтобы все указатели, соответствующие условиям, были const
, например. int * const
. Если я правильно понимаю, он не требует указателей и ссылок, указывающих на const
объекты, например. const int *
или const int &
. На самом деле на него распространяется другое правило (но только для параметров!):
Правило 7-1-2 (обязательное) Указатель или ссылочный параметр в функции должен быть объявлен как указатель на const или ссылку на const, если соответствующий объект не изменяется.
Итак, применимо ли правило 7-1-1 к ссылкам вообще? Ссылка не может быть перепривязана после того, как она была создана, поэтому ее следует рассматривать как указатель const
. Поэтому все ссылки должны автоматически соответствовать правилу 7-1-1.
EDIT (на основе комментариев Lightness Races in Orbit , Ричард Криттен и Питер и мои эксперименты): Или правило применяется к типу объекта, на который ссылаются, в случае ссылок? Я имею в виду const int &
против int &
аналогично const int
против int
? Я спрашиваю, потому что моя программа проверки MISRA C++ продолжает сообщать о нарушениях по ссылкам… Пример ее поведения:
class A
{
int property;
public:
A(int param) : property(param) {} // violation: should be: const int param
int get_property() const { return property; }
void set_property(int param) { property = param; } // violation: should be: const int param
};
class ConstA
{
const int property;
public:
ConstA(int param) : property(param) {} // violation: should be: const int param
int get_property() const { return property; }
// setter not allowed
};
void example1()
{
const A const_obj_A(1);
A nonconst_obj_A(2);
ConstA nonconst_obj_constA(3); // OK: used to create a non-const reference
const A& const_ref_A = nonconst_obj_A;
A& nonconst_ref_A = nonconst_obj_A; // OK: setter called
nonconst_ref_A.set_property(4);
ConstA& const_ref_constA = nonconst_obj_constA; // violation: no modification
// In fact, it seems to be impossible to make
// a non-violating ConstA& declaration.
// The only chance is to make another non-const reference
// but the last declaration in the chain will still violate.
}
void example2()
{
const A const_obj_A(1);
A nonconst_obj_A(2);
ConstA nonconst_obj_constA(3); // violation: used only in const reference
const A& const_ref_A = nonconst_obj_A;
A& nonconst_ref_A = nonconst_obj_A; // violation: no modification using the ref.
const ConstA& const_ref_constA = nonconst_obj_constA;
}