В чем разница между константный инт*, константный тип int * const и int строительства *?
Я всегда путаю, как использовать const int*
, const int * const
и int const *
правильно. Существует ли набор правил, определяющих, что вы можете и не можете сделать?
Я хочу знать все "делать" и "не делать" с точки зрения назначений, перехода к функциям и т. д.
14 ответов
прочитайте его назад (как управляется По Часовой Стрелке / Спиральное Правило):
-
int*
- указатель на int -
int const *
- указатель на const int -
int * const
- const указатель на int -
int const * const
- const указатель на const int
первое const
может быть по обе стороны от типа так:
-
const int *
==int const *
-
const int * const
==int const * const
если вы хотите сойти с ума, вы можете сделать такие вещи:
-
int **
- указатель на указатель на int -
int ** const
- указатель const на указатель на int -
int * const *
- указатель на указатель const на int -
int const **
- указатель на указатель на const int -
int * const * const
- указатель 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
указатели.
для тех, кто не знает о правиле по часовой стрелке / спирали: Начните с имени переменной, переместите clockwisely (в данном случае назад) к следующему указатель или тип. Повторяйте до конца выражения.
вот демо:
Я думаю все уже ответили, но я просто хочу добавить, что вы должны остерегаться typedef
s! Это не просто замена текста.
например:
typedef char *ASTRING;
const ASTRING astring;
тип astring
и char * const
, а не const char *
. Это одна из причин, почему я всегда склонен ставить const
справа от типа, а не в начале.
как почти все указали:
в чем разница между const X* p
, X* const p
и const X* const p
?
вы должны прочитать объявления указателей справа налево.
const X* p
означает "p указывает на X, который является const": объект X не может быть изменен через p.
X* const p
означает, что "p-указатель const на X, который не является const": вы не можете изменить сам указатель p, но вы можете изменить объект X через p.
const X* const p
означает, что "p-указатель const на X, который является const": вы не можете изменить сам указатель p, и вы не можете изменить объект X через p.
-
постоянные ссылки:
ссылка на переменную (здесь int), которая является постоянной. Мы передаем переменную как ссылку в основном, потому что ссылки меньше по размеру, чем фактическое значение, но есть побочный эффект, и это потому, что это похоже на псевдоним фактической переменной. Мы можем случайно изменить основную переменную через наш полный доступ к псевдониму, поэтому мы делаем ее постоянной, чтобы предотвратить эту сторону эффект.
int var0 = 0; const int &ptr1 = var0; ptr1 = 8; // Error var0 = 6; // OK
-
константными указателями
как только постоянный указатель указывает на переменную, он не может указывать на любую другую переменную.
int var1 = 1; int var2 = 0; int *const ptr2 = &var1; ptr2 = &var2; // Error
-
указатель на константу
указатель, через который нельзя изменить значение переменной, на которую он указывает, известен как указатель на константу.
int const * ptr3 = &var2; *ptr3 = 4; // Error
-
постоянный указатель на a константа
постоянный указатель на константу-это указатель, который не может изменить адрес, на который он указывает, и не может изменить значение, хранящееся по этому адресу.
int var3 = 0; int var4 = 0; const int * const ptr4 = &var3; *ptr4 = 1; // Error ptr4 = &var4; // Error
этот вопрос показывает точно почему мне нравится делать все так, как я упомянул в своем вопросе является ли const после идентификатора типа приемлемым?
короче говоря, я нахожу самый простой способ запомнить правило, что "const" идет после то, к чему это относится. Поэтому в вашем вопросе " int const * "означает, что int постоянен, а" int * const " означает, что указатель постоянен.
Если кто-то решит поставить его в очень фронт (например: "const int *"), в качестве специального исключения в этом случае он применяется к вещи после нее.
многие люди любят использовать это специальное исключение, потому что они думают, что это выглядит лучше. Мне это не нравится, потому что это исключение, и поэтому все путает.
общее правило заключается в том, что const
ключевое слово относится к тому, что предшествует ему немедленно. Исключение, начало const
относится к следующему.
-
const int*
это то же самое, чтоint const*
и означает "указатель на константу типа int". -
const int* const
это то же самое, чтоint const* const
и означает "постоянный указатель на константу int".
Edit: Для DOS и don'TS, если ответ не достаточно, не могли бы вы быть более точными о том, чего вы хотите?
простое использование 'const'
самое простое использование-объявить именованную константу. Для этого объявляется константа, как если бы она была переменной, но перед ней добавляется "const". Необходимо инициализировать его немедленно в конструкторе, потому что, конечно, нельзя установить значение позже, так как это изменило бы его. Например,
const int Constant1=96;
создаст целочисленную константу, невообразимо называемую 'Constant1', со значением 96.
такие константы полезны для параметры, которые используются в программе, но не должны быть изменены после компиляции программы. Он имеет преимущество для программистов над командой "#define " препроцессора C в том, что он понимается и используется самим компилятором, а не просто заменяется в текст программы препроцессором до достижения основного компилятора, поэтому сообщения об ошибках гораздо более полезны.
Он также работает с указателями, но нужно быть осторожным, где с 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
у меня были те же сомнения, что и у вас, пока я не наткнулся на это книги гуру C++ Скотт Мейерс. Обратитесь к третьему пункту в этой книге, где он подробно рассказывает об использовании const
.
просто следуйте этому совету
- если слово
const
появляется слева от звездочки, на что указывает константа - если слово
const
появляется справа от звездочки, сам указатель является константой - если
const
появляется с обеих сторон оба постоянны
есть много других тонких точек, окружающих правильность const в C++. Я полагаю, что вопрос здесь просто был о C, но я приведу некоторые связанные примеры, так как тег c++:
-
вы часто передаете большие аргументы, такие как строки, как
TYPE const &
что предотвращает изменение или копирование объекта. Пример :TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }
но
TYPE & const
бессмысленно, потому что ссылки всегда константа. -
вы всегда должны обозначить методы класса, которые не изменяют класс
const
, в противном случае вы не можете вызвать метод изTYPE const &
ссылка. Пример :bool TYPE::operator==(const TYPE &rhs) const { ... }
-
существуют общие ситуации, когда и возвращаемое значение, и метод должны быть const. Пример :
const TYPE TYPE::operator+(const TYPE &rhs) const { ... }
на самом деле, методы const не должны возвращать данные внутреннего класса как a ссылка на non-const.
-
в результате часто приходится создавать как метод const, так и метод non-const с использованием перегрузки const. Например, если вы определяете
T const& operator[] (unsigned i) const;
, тогда вы, вероятно, также захотите версию non-const, данную :inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }
Afaik, в C нет функций const, функции, не являющиеся членами, не могут сами быть const в C++, методы const могут иметь побочные эффекты, и компилятор не может использовать const функции, чтобы избежать дублирования функций. На самом деле, даже простой int const &
ссылка может засвидетельствовать значение, к которому она относится быть изменены другими.
это просто, но сложно. Обратите внимание, что мы можем поменять const
квалификатор с любым типом данных (int
, char
, float
, etc.).
давайте рассмотрим приведенные ниже примеры.
const int *p
==>*p
доступно только для чтения [p
является указателем на постоянное целое число]
int const *p
==>*p
доступно только для чтения [p
является указателем на постоянное целое число]
int *p const
==> неправильно заявление. Компилятор выдает синтаксическая ошибка.
int *const p
==> p
доступно только для чтения [p
является постоянным указателем на целое число].
Как указатель p
здесь только для чтения, объявление и определение должны быть в одном месте.
const int *p const
==> неправильно заявление. Компилятор выдает синтаксическую ошибку.
const int const *p
==> *p
доступно только для чтения
const int *const p1
==> *p
и p
только для чтения [p
является постоянным указателем на константу целое.] Как указатель p
здесь только для чтения, объявление и определение должны быть в одном месте.
int const *p const
==> неправильно заявление. Компилятор выдает синтаксическую ошибку.
int const int *p
==> неправильно заявление. Компилятор выдает синтаксическую ошибку.
int const const *p
==> *p
доступно только для чтения и эквивалентно int const *p
int const *const p
==> *p
и p
только для чтения [p
постоянная указатель на постоянное целое число]. Как указатель p
здесь только для чтения, объявление и определение должны быть в одном месте.
синтаксис объявления C и c++ неоднократно описывался оригинальными разработчиками как неудачный эксперимент.
давайте имя тип "указатель наType
"; Я называю это Ptr_
:
template< class Type >
using Ptr_ = Type*;
теперь Ptr_<char>
- это указатель на char
.
Ptr_<const char>
указатель const char
.
и const Ptr_<const char>
это const
указатель на const char
.
там.
const с int с обеих сторон сделает указатель на константу типа int.
const int *ptr=&i;
или
int const *ptr=&i;
const после ' * ' сделает постоянный указатель на int.
int *const ptr=&i;
в этом случае все эти указатель на постоянное целое число, но ни один из них не является постоянным указателем.
const int *ptr1=&i, *ptr2=&j;
в этом случае все указатель на постоянное целое число и ptr2-это постоянный указатель к константе integer. Но ptr1 не является постоянным указателем.
int const *ptr1=&i, *const ptr2=&j;
это в основном касается второй строки:лучшие практики, назначения, параметры функций и т. д.
общей практикой. Попробуйте сделать все const
Что вы можете. Или, говоря по-другому, сделать все const
для начала, а затем удалите точно минимальный набор const
s необходимо, чтобы программа могла функционировать. Это будет большой помощью в достижении const-корректности и поможет гарантировать, что тонкие ошибки не будут введены, когда люди пытаются назначить в вещи, которые они не должны изменять.
избегайте const_cast как чумы. Есть один или два законных случая использования для него, но их очень мало и далеко между ними. Если вы пытаетесь изменить