Я просматриваю несколько примеров программ, чтобы заново познакомиться с C ++, и столкнулся со следующим вопросом. Во-первых, вот пример кода:
void print_string(const char * the_string)
{
cout << the_string << endl;
}
int main () {
print_string("What's up?");
}
В приведенном выше коде вместо параметра print_string мог быть const char * const the_string
. Что для этого будет правильнее?
Я понимаю, что разница в том, что один является указателем на постоянный символ, а другой - постоянным указателем на постоянный символ. Но почему оба эти действия работают? Когда это будет актуально?
const char *
намного лучше, потому что онconst
находится на противоположной стороне.Изменяемый указатель на изменяемый символ
Изменяемый указатель на постоянный символ
Постоянный указатель на изменяемый символ
Постоянный указатель на постоянный символ
источник
const char* p; --> constant pointer to mutable character
char *const p; --> mutable pointer to constant character
const char * p
так: «p - указатель на символьную константу» или изменяемый указатель на константный символ, как правильно утверждает Джеймс. то же самое со вторым :).const char * const
означает указатель, а также данные , указатель указывал на, являются как сопзом!const char *
означает, что только данные, на которые указывает указатель, являются константными. однако сам указатель не является константой.Пример.
источник
(Я знаю, что это старый, но я все равно хотел поделиться.)
Просто хотел уточнить ответ Томаса Мэтьюза. Правило правого-левого объявления типов C в значительной степени говорит: при чтении объявления типа C начинайте с идентификатора и идите вправо, когда вы можете, и уходите, когда вы не можете.
Лучше всего это пояснить парой примеров:
Пример 1
Начните с идентификатора, мы не можем пойти направо, поэтому идем налево
foo - константа ...
Продолжайте движение налево
foo - постоянный указатель на ...
Продолжайте движение налево
foo - постоянный указатель на char ...
Продолжайте движение налево
foo - постоянный указатель на константу char (Complete!)
Пример 2
Начните с идентификатора, мы не можем пойти направо, поэтому идем налево
foo - константа ...
Продолжайте движение налево
foo - постоянный указатель на ...
Продолжайте движение налево
foo - постоянный указатель на char (Complete!)
Пример 1337
Начните с идентификатора, но теперь мы можем идти направо!
foo - это массив из 8 ...
Нажмите на скобку, чтобы больше не могли идти вправо, идите влево
foo - это массив из 8 указателей на ...
Закончено в скобках, теперь можно идти вправо
foo - это массив из 8 указателей на функцию, которая возвращает ...
Больше ничего направо, иди налево
foo - это массив из 8 указателей на функцию, которая возвращает указатель на ...
Продолжайте движение налево
foo - это массив из 8 указателей на функции, который возвращает указатель на константу ...
Продолжайте движение налево
foo - это массив из 8 указателей на функции, который возвращает указатель на постоянный указатель на ...
Продолжайте движение налево
foo - это массив из 8 указателей на функции, который возвращает указатель на постоянный указатель на char ...
Продолжайте движение налево
foo - это массив из 8 указателей на функции, который возвращает указатель на постоянный указатель на константу типа char (Complete!)
Дальнейшее объяснение: http://www.unixwiz.net/techtips/reading-cdecl.html
источник
Многие предлагают читать спецификатор типа справа налево.
В обеих формах указатель указывает на постоянные данные или данные только для чтения.
Во второй форме указатель изменить нельзя; указатель всегда будет указывать на одно и то же место.
источник
Разница в том, что без дополнительных действий
const
программист может изменить внутри метода, на который указывает указатель; например:Это было бы незаконно, если бы подпись была
void print_string(const char * const the_string)
Многие программисты считают
const
ключевое слово extra слишком многословным (в большинстве случаев) и пропускают его, даже если оно было бы семантически правильным.источник
В последнем вы гарантируете, что не изменяете указатель и символ, в первом вы гарантируете только то, что содержимое не изменится, но вы можете перемещать указатель.
источник
Нет причин, по которым ни один из них не работал бы. Все, что
print_string()
нужно сделать, это распечатать значение. Он не пытается его изменить.Хорошая идея - создать функцию, которая не изменяет аргументы mark как const. Преимущество состоит в том, что переменные, которые нельзя изменять (или вы не хотите изменять), можно передавать этим функциям без ошибок.
Что касается точного синтаксиса, вы хотите указать, какой тип аргументов «безопасен» для передачи в функцию.
источник
Я думаю, что это редко бывает актуально, потому что ваша функция не вызывается с такими аргументами, как & * the_string или ** the_string. Сам указатель является аргументом типа значения, поэтому, даже если вы измените его, вы не собираетесь изменять копию, которая использовалась для вызова вашей функции. Версия, которую вы показываете, гарантирует, что строка не изменится, и я думаю, что в данном случае этого достаточно.
источник
const char *
означает, что вы не можете использовать указатель, чтобы изменить то, на что он указывает. Однако вы можете изменить указатель, чтобы он указывал на что-нибудь еще.Рассматривать:
Параметр является неконстантным указателем на const char, поэтому его можно изменить на другое
const char *
значение (например, на постоянную строку). Если же мы написали по ошибке,*text = '\0'
то получим ошибку компиляции.Возможно, если вы не собираетесь изменять то, на что указывает параметр, вы можете создать параметр
const char * const text
, но это не является обычным делом. Обычно мы разрешаем функциям изменять значения, передаваемые параметрам (поскольку мы передаем параметры по значению, любое изменение не влияет на вызывающего).Кстати: это хорошая практика, которой следует избегать,
char const *
потому что она часто неправильно понимается - это означает то же самоеconst char *
, но слишком многие люди читают ее как значениеchar * const
.источник
const char *
и подписьюchar const *
- то, как вы сформулировали свой BTW, действительно помогло!Почти все остальные ответы верны, но они упускают из виду один аспект: когда вы используете дополнительный
const
параметр в объявлении функции, компилятор по существу проигнорирует его. На мгновение давайте проигнорируем сложность вашего примера, являющегося указателем, и просто воспользуемся расширениемint
.объявляет ту же функцию, что и
Только в определении функции есть дополнительное
const
значение:Это определение совместимо с любым из приведенных выше заявлений. Вызывающего абонента это не волнует
x
-const
это деталь реализации, не имеющая отношения к месту вызова.Если у вас есть
const
указатель наconst
данные, применяются те же правила:Немногие программисты на C ++ беспокоятся о создании параметров
const
, даже если они могут быть такими, независимо от того, являются ли эти параметры указателями.источник
const
параметр в свой параметр функции в определении, но не в объявлении.Разница между ними в том, что char * может указывать на любой произвольный указатель. Const char *, напротив, указывает на константы, определенные в разделе DATA исполняемого файла. И, как таковой, вы не можете изменять значения символов строки const char *.
источник
const char*
может указывать куда угодно.