Переход на const
является, так сказать, улицей с односторонним движением.
Вы можете конвертировать из T *
в T const *
неявно.
Преобразование из T const *
в T *
требует явного приведения. Даже если вы начали с T *
, а затем преобразованы в T const *
, конвертация назад в T *
требует явного приведения, хотя это действительно просто «восстановление» доступа, с которым вы должны были начать.
Обратите внимание, что во всем, T const *
и const T *
в точности эквивалентны, и T
означает «некоторого произвольного типа» (char
в вашем примере, но может так же легко быть что-то еще, как int
или my_user_defined_type
).
char *
Инициализации из строкового литерала (например, char *s = "whatever";
) допускаются, даже если он нарушает это общее правило (в буквальном смысле сам по себе является в основном const
, но вы создаете неконстантный указатель на него). Это просто потому, что от этого зависит много кода, и никто не хотел нарушать этот код, поэтому у них есть правило, позволяющее это делать. Однако это правило было устаревшим, поэтому, по крайней мере теоретически, какой-то будущий компилятор мог бы отбросить код, который зависит от него.
Поскольку строковый литерал в основном является const
, любая попытка его изменения приводит к неопределенному поведению. В большинстве современных систем это приведет к завершению процесса, поскольку память, хранящая строковый литерал, будет отмечена как «только для чтения». Это не единственный возможный результат. Например, еще во времена MS-DOS это часто бывает успешным. Тем не менее, он все еще может иметь причудливые побочные эффекты. Например, многие компиляторы «знали», что строковые литералы должны быть доступны только для чтения, поэтому они «сливают» идентичные строковые литералы.Поэтому, если у вас что-то вроде:
char *a = "Peter"; a[1] = 'a';
char *b = "Peter";
cout << b;
Компилятор будет иметь «слиты» a
и b
на самом деле указывают на ту же память, - так что, когда вы изменили a
, что изменения будут также влиять на b
, поэтому он будет печатать «Патер» вместо «Петра».
Обратите внимание, что строковые литералы не обязательно должны быть полностью идентичными для этого. Пока один был идентичен концу другой, они могут быть объединены:
char *a = "this?";
char *b = "What's this?";
a[2] = 'a';
a[3] = 't';
cout << b; // could print "What's that?"
Мандаты одно поведения не имел смысла, так что результат был (и есть) просто не определен.
Что значит 'name (c)' не работает? Определите «работы». –
@Eitan недействительное преобразование из const char * в char * – tuks
'' Peter '' is 'const char [6]', а не 'const char *'. – chris