В C ++ допустимо ли использование const после идентификатора типа? - PullRequest
22 голосов
/ 12 июня 2009

Моему коллеге 0 на 2 по вопросам, которые он вдохновил ( 1 , 2 ), поэтому я решил дать ему шанс наверстать упущенное.

Наше последнее разногласие связано со стилем вопроса о том, где поместить "const" в декларации.

Он считает, что он должен идти либо перед типом, либо после указателя. Причина в том, что это то, что обычно делают все остальные, и другие стили могут вводить в заблуждение. Таким образом, указатель на константу int и константный указатель на int будут соответственно:

const int *i;
      int * const i;

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

Таким образом, указатель на константу int и указатель на int будут соответственно:

int const * i;
int * const i;

В качестве дополнительного преимущества, выполнение таких действий облегчает понимание более глубоких уровней косвенности. Например, указатель на постоянный указатель на int будет ясно:

int * const * i;

Мое утверждение заключается в том, что если кто-то просто научится этому по-своему, у него будет мало проблем с выяснением того, с чем работает вышеприведенное.

В конечном итоге проблема заключается в том, что он считает, что помещать const после int настолько ужасно некрасиво и настолько вредно для читабельности, что его следует запретить в руководстве по стилю. Конечно, я думаю, что если что-нибудь будет в руководстве, предложим сделать это по-своему, но в любом случае нам не следует запрещать один подход.

Edit: Я получил много хороших ответов, но ни один из них не касался моего последнего абзаца («Основная проблема»). Многие люди настаивают на последовательности, но разве это так желательно в этом случае, что это хорошая идея, чтобы запретить другой способ сделать это, а не просто обескураживать это?

Ответы [ 15 ]

3 голосов
/ 12 июня 2009

Лично я (и это личное предпочтение) я нашел чтение типов объявлений справа налево проще всего. Особенно, когда вы начинаете бросать ссылки в микс.

std::string const&  name = plop; // reference to const string.

const std::string&  flame =plop; // reference to string const;
                                 // That works better if you are German I suppose :-)
2 голосов
/ 13 ноября 2009

Я согласен с вами обоими. Вы должны поставить const после типа. Я также нахожу глядя на это мерзостью, которая должна быть уничтожена. Но мой недавний набег на чудеса параметров константного значения помог мне понять, почему ставить const в секунду имеет смысл.

int *
int const *
int * const
int const * const

Просто глядя на это, волосы на моей шее стоят. Я уверен, что это смутит моих коллег.

РЕДАКТИРОВАТЬ: Мне просто интересно использовать это в классах:

class Foo {
    Bar* const bar;
    Foo(const Foo&) = delete; // would cause too many headaches
public:
    Foo() : bar(new Bar) {}
    ~Foo() { delete bar; }
};

bar в этом примере функционально эквивалентен Bar&, но находится в куче и может быть удален. В течение срока действия каждого Foo, с ним будет связан один Бар.

2 голосов
/ 13 ноября 2009

Я хотел бы использовать следующую форму для объявления "явных констант" . В этом случае само значение является константой, поэтому я ставлю сначала «const» (, то же самое, что и Bjarne ), чтобы подчеркнуть, что константа должна проявляться во время компиляции и использоваться как таковая для конкретных оптимизаций с помощью компилятор.

const int i = 123;

Для объявления ссылок, которые не будут использоваться для изменения значения, я использую следующую форму, которая подчеркивает тот факт, что идентификатор является «постоянной ссылкой». Указанное значение может быть или не быть константой. [Связанное обсуждение: Вы бы даже использовали «const» для параметров функции, если бы они не были указателями или ссылками? Использование 'const' для параметров функции ]

void fn( int const & i );

Для указателей я использую ту же форму, что и для ссылок, по сути по той же причине (хотя термин «постоянный указатель» кажется немного более неоднозначным, чем «постоянная ссылка»).

void fn( int const * i );

Кроме того, как заметил другой автор, эта форма остается согласованной, если у вас есть несколько уровней косвенности.

void fn( int const * const * i );

Последний сценарий, когда вы объявляете указатель, который является константой, довольно редок в моем опыте с C ++. В любом случае, у вас действительно нет выбора здесь. [Этот случай демонстрирует, что наиболее последовательный подход заключался бы в том, чтобы поставить слово «const» после типа - поскольку для этого конкретного объявления требуется .]

void fn( int * const i );

... если вы не используете typedef.

typedef int * IntPtr;

void fn1( const IntPtr i );
void fn2( IntPtr const i );

Последнее замечание: если вы не работаете в домене низкого уровня, большая часть кода C ++ не должна никогда не объявлять указатель . Следовательно, этот аспект этого обсуждения, вероятно, больше относится к C.

2 голосов
/ 13 июня 2009

Правила хороши для подражания. Чем проще правила, тем лучше. Const идет справа от того, что const.

Возьмите эту декларацию:

INT главный (int const argc , char const * const * const argv ) ...

1 голос
/ 26 октября 2012

В современном C ++ 11 вы также можете использовать шаблон typedefs, чтобы внести ясность в сложные объявления:

template<typename T>
using Const = const T;

template<typename T>
using Ptr = T*;

Три заявления, которые вы упомянули в своем вопросе:

int const * a;
int * const b;
int * const * c;

будет тогда записано как:

Ptr<Const<int>> a;
Const<Ptr<int>> b;
Ptr<Const<Ptr<int>>> c;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...