В чем разница между const int *, const int * const и int const *? - PullRequest
1195 голосов
/ 17 июля 2009

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

Я хочу знать все, что можно и чего нельзя делать в отношении назначений, передачи функций и т. Д.

Ответы [ 16 ]

2009 голосов
/ 17 июля 2009

Прочитать его в обратном направлении (как управляется по часовой стрелке / правилу спирали ):

  • int* - указатель на int
  • int const * - указатель на const int
  • int * const - постоянный указатель на int
  • int const * const - постоянный указатель на const int

Теперь первый const может быть с любой стороны типа, так:

  • const int * == int const *
  • const int * const == int const * const

Если вы хотите сойти с ума, вы можете сделать что-то вроде этого:

  • int ** - указатель на указатель на int
  • int ** const - постоянный указатель на указатель на int
  • int * const * - указатель на константный указатель на int
  • int const ** - указатель на указатель на const int
  • int * const * const - константный указатель на константный указатель на int
  • ...

И чтобы убедиться, что мы ясно понимаем значение const

const int* foo;
int *const bar; //note, you actually need to set the pointer 
                //here because you can't change it later ;)

foo - переменный указатель на постоянное целое число. Это позволяет вам изменить то, на что вы указываете, но не значение, на которое вы указываете. Чаще всего это наблюдается в строках в стиле C, где у вас есть указатель на const char. Вы можете изменить строку, на которую вы указываете, но вы не можете изменить содержимое этих строк. Это важно, когда сама строка находится в сегменте данных программы и не должна изменяться.

bar - это постоянный или фиксированный указатель на значение, которое можно изменить. Это как ссылка без лишнего синтаксического сахара. По этой причине обычно вы используете ссылку, в которой вы используете указатель T* const, если только вам не нужно разрешить указатели NULL.

305 голосов
/ 10 июля 2015

Для тех, кто не знает о правиле по часовой стрелке / спирали: Начните с имени переменной, двигайтесь по часовой стрелке (в данном случае назад) к следующему указателю или типу . Повторяйте, пока выражение не закончится.

Вот демоверсия:

pointer to int

const pointer to int const

pointer to int const

pointer to const int

const pointer to int

134 голосов
/ 17 июля 2009

Я думаю, что все уже здесь ответили, но я просто хочу добавить, что вы должны остерегаться typedef s! Они НЕ просто текстовые замены.

Например:

typedef char *ASTRING;
const ASTRING astring;

Тип astring - char * const, а не const char *. Это одна из причин, по которой я всегда стараюсь ставить const справа от шрифта, а не в начале.

48 голосов
/ 17 июля 2009

Как почти все отметили:

В чем разница между const X* p, X* const p и const X* const p?

Вы должны прочитать объявления указателя справа налево.

  • const X* p означает «p указывает на постоянный X»: объект X нельзя изменить с помощью p.

  • X* const p означает «p является константным указателем на X, который не является константным»: вы не можете изменить сам указатель p, но вы можете изменить X-объект с помощью p.

  • const X* const p означает «p - это константный указатель на X, который является константой»: вы не можете изменить сам указатель p, а также не можете изменить объект X с помощью p.

43 голосов
/ 18 мая 2014
  1. Постоянная ссылка:

    Ссылка на переменную (здесь int), которая является постоянной. Мы передаем переменную в основном как ссылку, потому что ссылки меньше по размеру, чем фактическое значение, но есть побочный эффект, и это потому, что это похоже на псевдоним для фактической переменной. Мы можем случайно изменить основную переменную через наш полный доступ к псевдониму, поэтому мы устанавливаем ее постоянной, чтобы предотвратить этот побочный эффект.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
    
  2. Указатели констант

    Как только постоянный указатель указывает на переменную, он не может указывать на любую другую переменную.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
    
  3. Указатель на постоянную

    Указатель, с помощью которого нельзя изменить значение переменной, на которую он указывает, называется указателем на константу.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
    
  4. Указатель константы на постоянную

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

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error
    
17 голосов
/ 17 июля 2009

Общее правило заключается в том, что ключевое слово const относится к тому, что ему предшествует. Исключение: начало const относится к следующему.

  • const int* совпадает с int const* и означает «указатель на константу int» .
  • const int* const совпадает с int const* const и означает «постоянный указатель на константу int» .

Edit: Что нужно делать и не делать, если этого ответа недостаточно, не могли бы вы быть более точным относительно того, что вы хотите?

16 голосов
/ 17 июля 2009

Этот вопрос показывает точно , почему мне нравится делать вещи так, как я упомянул в моем вопросе является константой после идентификатора типа?

Короче говоря, я считаю, что самый простой способ запомнить правило - это то, что "const" идет после того, к чему оно относится. Итак, в вашем вопросе «int const *» означает, что int является константой, а «int * const» будет означать, что указатель является константой.

Если кто-то решит поместить его в самое начало (например, «const int *»), то в качестве специального исключения в этом случае он применяется к вещи после нее.

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

14 голосов
/ 17 июля 2009

Простое использование const.

Самое простое использование - объявить именованную константу. Для этого нужно объявить константу так, как если бы она была переменной, но перед ней добавить const. Нужно немедленно инициализировать его в конструкторе, потому что, конечно, нельзя установить значение позже, так как это изменило бы его. Например:

const int Constant1=96; 

создаст целочисленную константу, не названную по имени Constant1, со значением 96.

Такие константы полезны для параметров, которые используются в программе, но их не нужно менять после компиляции программы. Для программистов она имеет преимущество перед командой препроцессора C #define в том, что она понимается и используется самим компилятором, а не просто подставляется препроцессором в текст программы до достижения основного компилятора, поэтому сообщения об ошибках гораздо более полезны.

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

const int * Constant2 

объявляет, что Constant2 является указателем переменной на постоянное целое число и:

int const * Constant2

- это альтернативный синтаксис, который делает то же самое, тогда как

int * const Constant3

объявляет, что Constant3 является постоянным указателем на целое число переменной и

int const * const Constant4

объявляет, что Constant4 является постоянным указателем на постоянное целое число. По сути, «const» применяется ко всему, что находится непосредственно слева от него (кроме случаев, когда там ничего нет, в этом случае оно применяется к тому, что непосредственно справа от него).

ref: http://duramecho.com/ComputerInformation/WhyHowCppConst.html

7 голосов
/ 21 марта 2015

У меня были те же сомнения, что и у вас, пока я не наткнулся на эту книгу Гуру С ++ Скотта Мейерса. Обратитесь к третьему пункту в этой книге, где он подробно рассказывает об использовании const.

Просто следуйте этому совету

  1. Если слева от звездочки появляется слово const, на что указывает постоянная
  2. Если справа от звездочки появляется слово const, сам указатель будет постоянным
  3. Если const появляется с обеих сторон, оба значения являются постоянными
5 голосов
/ 06 января 2016

Синтаксис объявления C и C ++ неоднократно описывался как неудачный эксперимент оригинальными проектировщиками.

Вместо этого давайте назовем указатель типа & ldquo; на Type & rdquo ;; Я назову это Ptr_:

template< class Type >
using Ptr_ = Type*;

Теперь Ptr_<char> является указателем на char.

Ptr_<const char> - указатель на const char.

И const Ptr_<const char> - это указатель const на const char.

Там.

enter image description here

...