const char * и char const * - это одно и то же?

81

Насколько я понимаю, constмодификаторы следует читать справа налево. Из этого я понял:

const char*

- это указатель, элементы char которого нельзя изменить, но сам указатель может, и

char const*

постоянный указатель на mutableсимволы.

Но я получаю следующие ошибки для следующего кода:

const char* x = new char[20];
x = new char[30];   //this works, as expected
x[0] = 'a';         //gives an error as expected

char const* y = new char[20];
y = new char[20];   //this works, although the pointer should be const (right?)
y[0] = 'a';         //this doesn't although I expect it to work

Итак ... что это? Я неправильно понимаю или мой компилятор (VS 2005)?

Лучиан Григоре
источник
35
Если сомневаетесь, всегда используйте правило спирали .
Alok Save
«... чьи элементы char могут быть изменены, но сам указатель может, и ...» - я думаю, вы хотели сказать «не могу» для одного из этих «может», но я не знаю, как Вы запутались, поэтому я не знаю, что исправить: P
detly
1
Попробуйте этот сайт: www.cdecl.org
yasouser
Компилятор никогда не ошибается;)
monolith

Ответы:

129

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

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

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

char * const constantPointerToMutableContent;

Чтобы защитить указатель и содержимое, на которое он указывает, используйте две константы.

char const * const constantPointerToConstantContent;

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

Грейсон
источник
23
«удобная стенография» - интересное описание чего-то, что не короче и не соответствует обычным правилам.
beetstra
Стандарт на самом деле не заботится о том, какой порядок вы используете. Раздел 7.1.6 показывает только оба места и говорит, что используйте его только в одном.
edA-qa mort-ora-y
1
@beetstra Согласен. Я изменил его на «удобный мысленный ярлык», чтобы было немного понятнее.
Грейсон
31

Это работает, потому что оба они одинаковы. Может вы в этом запутались,

const char*  // both are same
char const*

и

char* const  // unmutable pointer to "char"

и

const char* const  // unmutable pointer to "const char"

[Чтобы запомнить это, вот простое правило: '*' сначала влияет на всю левую часть экрана ]

iammilind
источник
Хорошо, теперь я понял. Большое спасибо.
Лучиан Григоре
1
unmutable pointer to char*.Это неизменяемый указатель, указывающий на charnot char *.
Alok Save
25

Это потому, что правило:

ПРАВИЛО: constсвязывает слева, если слева ничего нет, то связывает вправо :)

Итак, посмотрите на них как на:

(const --->> char)*
(char <<--- const)*

оба одинаковые! о, и --->>и <<---НЕ являются операторами, они просто показывают, к чему constпривязываются.

Аканкш
источник
2
да, правильный оператор есть, -->>и он работает только со значениями. Попробуйте int i = 8; std::cout << (i -->> 1) << std::endl;:)
Александр Малахов
11

(из 2 простых вопросов инициализации переменной )

Действительно хорошее практическое правило относительно const:

Читайте объявления справа налево.

(см. Vandevoorde / Josutiss «Шаблоны C ++: полное руководство»)

Например:

int const x; // x is a constant int
const int x; // x is an int which is const

// easy. the rule becomes really useful in the following:
int const * const p; // p is const-pointer to const-int
int const &p;        // p is a reference to const-int
int * const * p;     // p is a pointer to const-pointer to int.

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

(: sisab retcarahc-rep a no ton, sisab nekot-rep a no tfel-ot-thgir naem I hguohT: tidE

Себастьян Мах
источник
+1 Это фантастика, спасибо! Я пытался осмыслить вещи const char* constцелую вечность, и благодаря вам теперь я понял.
OMGtechy
5

Вот как я всегда пытаюсь интерпретировать:

char *p

     |_____ start from the asterisk. The above declaration is read as: "content of `p` is a `char`".

char * const p

     |_____ again start from the asterisk. "content of constant (since we have the `const` 
            modifier in the front) `p` is a `char`".

char const *p

           |_____ again start from the asterisk. "content of `p` is a constant `char`".

Надеюсь, поможет!

ясусер
источник
0

В обоих случаях вы указываете на постоянный символ.

const char * x  //(1) a variable pointer to a constant char
char const * x  //(2) a variable pointer to a constant char
char * const x  //(3) a constant pointer to a variable char
char const * const x //(4) a constant pointer to a constant char
char const * const * x //(5) a variable pointer to a constant pointer to a constant char
char const * const * const x //(6) can you guess this one?

По умолчанию constприменяется к тому, что находится непосредственно слева, но может применяться к тому, что находится непосредственно справа от него, если ему ничего не предшествует, как в (1).

Лино Медиавилла
источник
Последний: указатель на постоянную переменную, на постоянный указатель, на постоянный символ.
Secko 02
Если под «указателем на постоянную переменную» вы подразумеваете «указатель на постоянную переменную», значит, вы прибили его, братан!
Lino Mediavilla
Ну, в (5) это указатель переменной на постоянный указатель на постоянный символ просто потому, что нет «const» справа от последней звездочки перед идентификатором «x». Но в (6) он становится постоянным указателем, а все остальное остается прежним.
Lino Mediavilla