Почему указатель не может быть инициализирован с другим указателем на const char? - PullRequest
0 голосов
/ 19 ноября 2018

Вот еще одна проблема «переизобретения за рулем», которую нам дали во введении к классам C ++:

Напишите функцию, которая возвращает позицию первого вхождения последовательность символов в строке, то есть вариация strstr функция.

Я начал писать функцию следующим образом:

int strstr2(const char *text, const char *pattern) {
    int pos = 0;
    char *temp;
    temp = text;
}

Я думал, что запомню адрес первого символа строки для будущего использования в функции, но компилятор сказал:

Значение типа "const char *" нельзя присвоить объекту типа "char *".

Я знаю, что нельзя изменить константу после ее инициализации, но почему я не могу назначить указатель на постоянный символ другому неконстантному указателю?

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

Мой второй вопрос: какой обходной путь? Как я могу определить указатель, указывающий на начало строки?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Это часть безопасности типа const-правильности.Поскольку text является указателем на const char, вы не можете изменять символы, на которые он указывает, через него.Это хорошая вещь и мера безопасности.

Однако вся безопасность будет признана недействительной, если будет разрешено присвоить ей указатель на неконстантный символ!Потому что чем бы вы изменили символ через указатель и обошли безопасность!

Из-за этого это назначение не разрешено.Чтобы исправить это, отметьте ваш temp как указатель на const char: const char* temp.

0 голосов
/ 19 ноября 2018

Если назначение будет разрешено, вы сможете по закону написать:

*temp = 'x'; // write to char* is legal in general

Но в этом случае это будет плохо, потому что вы будете писать в константу.

Стандарт может содержать , в котором говорится, что присвоение temp = text является допустимым, а *text = 'x' - неопределенным поведением, но это не имеет смысла, потому что единственная разница между T* и const T* является ли вы можете написать ему.

Поэтому вполне логично, что C ++ запрещает присваивать типу T* значение типа const T*, чтобы избавить вас от дальнейших ошибок, и вместо этого вынуждает вас использовать const char* temp; temp = text; в этом случае.

0 голосов
/ 19 ноября 2018

Это связано с const-правильностью .const char *text означает, что text - указатель на константу char.Это означает, что если вы попытаетесь сделать что-то вроде

*text = 'a'

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

char *temp;
temp = text;

, тогда вы могли бы сделать

*temp = 'a'

, и не было бы ошибки, даже если вы только что изменили объект const.Вот почему C ++ требует, чтобы вы использовали const_cast, если вы действительно хотите отбросить const (есть несколько вариантов использования для этого, но они далеко не то, что вы обычно хотите делать).


Опасно, внизу будут драконы.Будьте очень, очень осторожны, если вы решите использовать const_cast

Допустим, вам приходится иметь дело со старым вызовом API, который принимает только char*, , но гарантирует, что он не изменит , тогда вы можете использовать что-то вроде

int wrap_api(const char *text)
{
    return api_call(const_cast<char*>(text));
}

, и это будет "хорошо", поскольку api_call гарантирует, что строка не будет изменена.С другой стороны, если api_call может измениться, то это будет допустимо только в том случае, если то, на что указывает text, на самом деле не равно, как

char foo[] = "test"
wrap_api(foo);

, то будет допустимо, если foo будет изменено, но

const char foo* = "test"
wrap_api(foo);

будет недопустимым, если foo будет изменен и поведение не определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...