Подтвердить что ты не робот

В С++ есть "const" после допустимого идентификатора типа?

Мой сотрудник 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: У меня есть много хороших ответов, но никто действительно не обращается к моему последнему абзацу ( "Конечная проблема" ). Многие люди утверждают о последовательности, но настолько ли желательно, чтобы в этом случае было бы неплохо запретить другой способ сделать это, а не просто обескураживать его?

4b9b3361

Ответ 1

Самое главное - консистенция. Если для этого нет рекомендаций по кодированию, выберите один и придерживайтесь его. Но если ваша команда уже имеет де-факто стандарт, не меняйте ее!

Тем не менее, я думаю, что более распространенным является

const int* i;
int* const j;

потому что большинство людей пишут

const int n;

вместо

int const n;

Боковое примечание - простой способ чтения указателя const ness - прочитать декларацию, начинающуюся справа.

const int* i; // pointer to an int that is const
int* const j; // constant pointer to a (non-const) int
int const* aLessPopularWay; // pointer to a const int

Ответ 2

Там класс примеров, где поместить константу справа от типа, также помогает избежать путаницы.

Если у вас есть тип указателя в typedef, тогда невозможно изменить константу типа type:

typedef int * PINT;
const PINT pi;

'pi' все еще имеет тип 'int * const', и это то же самое, где вы пишете 'const'.

Ответ 3

Надеюсь, что это объяснение из "Вопросы по стилю и технике" от B. Stroustrup даст вам определенный ответ.

Часто задаваемые вопросы по стилю и технике Bjarne Stroustrup С++


Я предпочитаю лично:

int const* pi;
int* const pi;

Потому что const идентифицирует левый токен, который должен быть const.

И вы определенно сохраняете такую ​​же последовательность при использовании smth:

int const* const pi;

Вместо того, чтобы писать непоследовательно:

const int* const pi;

И что произойдет, если у вас есть указатель на указатель и так далее:

int const* const* const pi;

Вместо:

const int* const* const pi;

Привет,

Ованес

Ответ 4

Я был на конференции, где Бьярн Страуструп давал презентацию, и он использовал что-то вроде const int * i; Кто-то спросил его, почему этот стиль, и он ответил (перефразируя): "людям нравится видеть сначала, когда что-то постоянно".

Ответ 5

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

Я нахожу, что вариация int* const blah достаточно редка, что обычно не имеет особого значения для более общего определения назад. Я вообще не поклонник чего-либо, что даже слегка затушевывает код в общем случае, хотя в исключительном случае это может дать некоторую номинальную выгоду.

См. также "if (1 == a)". Некоторым людям очень нравится писать код, который не читается как английский. Я не из тех людей.

Действительно, хотя правила const являются простыми. Посмотрите налево, затем направо. Так просто, что я не думаю, что это стоит внимания в руководстве по стилю.

Ответ 6

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

class MyClass
{
    public:
        int foo() const;
};

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

Чем короче руководство по стилю, тем более вероятно, что разработчики последуют за ним. И возможно кратчайшее правило, и единственное правило, которое даст вам последовательность:

Ключевое слово const всегда отслеживает все, на что ссылается.

Итак, я сказал бы 0: 3 для вашего коллеги.

Относительно вашей "конечной проблемы": ради руководства по стилю не имеет значения, ведет ли руководство "отговаривает" или "запрещает" то, с чем оно говорит. Это социальная проблема, политика. Руководство по стилю должно быть максимально четким и коротким. Длинные руководства по стилю просто игнорируются всеми (кроме руководства в поиске кого-то, кто виноват), поэтому просто пишите "делать" или "не делать" и указывайте, что вы делаете с нарушениями руководства в другом месте (например, в политике компании о том, как проводятся экспертные обзоры).

Ответ 7

Пока нет значимой разницы между const int и int const (и я видел оба используемых стиля), существует разница между const int * и int * const.

В первом случае у вас есть указатель на const int. Вы можете изменить указатель, но вы не можете изменить значение, на которое оно указывает. Во втором - указатель const для int. Вы не можете изменить указатель (надеюсь, что он инициализирован по вашему вкусу), но вы можете изменить значение привязанного к int.

Правильное сравнение с const int * и int const *, которые оба являются указателями на const int.

Помните, что * не всегда работает так, как вам может понравиться. Объявление int x, y; будет работать так, как вы ожидаете, но int* x, y; объявляет один указатель на int и один int.

Ответ 8

Помещение "const" после объявления типа делает намного больше смысла, если вы тренируете себя, чтобы читать объявления типа С++ справа налево.

Я собираюсь привязать корову-орков к 0-для-3:)

Ответ 9

Лично я (и это личное предположение). Я считаю, что декларации типа чтения справа налево являются самыми легкими. Особенно, когда вы начинаете бросать ссылки в микс.

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 :-)

Ответ 10

Конечная проблема здесь заключается в том, что он считает, что установка const после int настолько невыразимо уродлива и настолько вредна для читаемости, что она должна быть запрещена в руководстве по стилю

Действительно?

Покажите мне программиста, который увязнет, ​​когда видит:

int foo() {
}

vs

int foo()
{
}

... и я покажу вам программиста, который не уделяет достаточно пристального внимания деталям.

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

EDIT: Это правда, что const int * и int * const не означает точно то же самое, но это не главное. Точка, сделанная сотрудником OP, заключалась в том, что различия в стиле делают код сложным для понимания и поддержания. Я не согласен с этим утверждением.

Ответ 11

Позвольте мне поместить мои 2 ¢ в обсуждение.

В современном С++ я рекомендую придерживаться int const вместо const int, чтобы выделить разницу между const и constexpr. Это помогло бы программисту запомнить, что const int нельзя всегда считать константой времени компиляции, потому что:

  • компилятор может (будет?) выделять для него память,
  • эта память может быть даже не защищена от записи (сегмент стека),
  • такая константа не может служить всем обязанностям constexpr может.

Ответ 12

Правила хороши. Упрощенные правила лучше. Констант справа от того, что const.

Возьмите это объявление:

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

Ответ 13

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

const int i = 123;

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

void fn( int const & i );

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

void fn( int const * i );

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

void fn( int const * const * i );

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

void fn( int * const i );

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

typedef int * IntPtr;

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

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

Ответ 14

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

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

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

EDIT: Мне просто интересно было использовать это в классах:

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 рядом с ним будет один Бар.

Ответ 15

В современном С++ 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;