Влияет ли правило MISRA C++ 7-1-1 на ссылки?

Правило 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;
}

person Melebius    schedule 22.02.2017    source источник
comment
Там написано переменная, поэтому я считаю, что если ссылка может быть сделана постоянной, она должна быть.   -  person Richard Critten    schedule 22.02.2017
comment
Если ваш вопрос касается ссылок, предоставьте соответствующий код со ссылками. ... ИМХО это правило очень слабое.   -  person knivil    schedule 22.02.2017


Ответы (2)


Нет, 7-1-1 не относится к ссылкам.

Объявление вида int32_t & const p2 — ерунда.

Единственная осмысленная const квалификация ссылки имеет форму const int32_t &p2 или эквивалентную int32_t const &p2. Тогда потребность в этих формах полностью покрывается в 7-1-2.

Misra 7-1-1 не нужно применять к таким ссылкам, потому что философия Misra состоит в том, чтобы указать ограничения, которых нет в языковом стандарте, а не переформулировать ограничения, уже указанные в языке (и принудительно применяемые компиляторами). Misra 7-1-1 требует, чтобы переменная (скажем, типа int32_t) была объявлена ​​const, если она не будет изменена, например i в приведенном примере. В стандартном C++ невозможно создать ссылку, отличную от const, на эту переменную, если только преобразование типа (также известное как «приведение») не используется для удаления constness. Правило Misra 5-2-5 требует, чтобы такие броски не использовались.

person Peter    schedule 22.02.2017
comment
Почти, но не совсем - 7-1-2 охватывает только параметры, если только нет текста, который ОП не цитировал. - person Lightness Races in Orbit; 22.02.2017
comment
@LightnessRacesinOrbit Вы правы. Правило 7-1-2 гласит: Это правило приводит к большей точности в определении интерфейса функции. Таким образом, оно не влияет на локальные переменные. Это делает 7-1-1 еще более сомнительным… - person Melebius; 22.02.2017
comment
@Melebius: Еще более странно, что далее говорится, что это означает, что указатель должен быть const, а не сам указатель. Что просто сбивает с толку. Как и в случае с руководством по стилю Google C++, я не согласен с теми, кто настаивает на соблюдении правил MISRA, как если бы они были законом. Или, ну, как если бы они были разумными. - person Lightness Races in Orbit; 22.02.2017
comment
@LightnessRacesinOrbit Спасибо за комментарии, я уточнил вопрос. - person Melebius; 22.02.2017
comment
Misra обычно не устанавливает требований, которые являются частью языка. Если объект является const, что потребовалось бы 7-1-1, если намерение не состоит в том, чтобы изменить его, то в C++ невозможно создать ссылку на него, отличную от const, если только преобразование типа (также известное как приведение) не используется для удалите квалификатор const. Компилятор C++ диагностирует ошибку. Хотя можно заставить компилятор подчиняться преобразованию типов, другое правило Misra (5-2-5) требует, чтобы такие приведения не использовались. Я отредактирую и добавлю комментарий по этому поводу в ближайшее время. - person Peter; 22.02.2017
comment
@Peter Спасибо за дополнение. Однако я имел в виду не это. Я добавил пример к моему вопросу, чтобы объяснить это. - person Melebius; 23.02.2017

Существует значительная семантическая разница между указателем C++ и ссылкой: ссылка НЕ ​​является объектом (переменной).

Это просто псевдоним объекта. Так что по строгому формальному смыслу 7-1-1 не применяется к ссылкам.

person Rost    schedule 22.02.2017
comment
И, даже если бы это было актуально, оно применялось бы имплицитно, как уже сказано в вопросе. Так что да, не вижу, как применяется 7-1-1. 7-2-2 — соответствующее правило, но, как ни странно, оно применяется только к параметрам функции. - person Lightness Races in Orbit; 22.02.2017
comment
Согласитесь, правила немного расплывчаты. 7-1-1 относится к переменным, но в примере показаны параметры функции. Неясно, действительно ли переменный термин включает в себя параметры и какова цель их различения в 7-1-2. - person Rost; 22.02.2017