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"

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


Хорошо, теперь я понял. Большое спасибо.
— Лучиан Григоре

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.