const char * і char const * - вони однакові?


81

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

const 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
Якщо ви сумніваєтесь, завжди використовуйте спіральне правило .
Алок Зберегти

"... чиї елементи char можуть бути змінені, але сам вказівник може, і ..." - Я думаю, ви мали намір сказати "не може" для одного з тих "can" s, але я не знаю як розгублений ти, тому я не знаю, що виправити: P
detly

1
Спробуйте на цьому веб-сайті: www.cdecl.org
yasouser

Компілятор ніколи не помиляється;)
моноліт

Відповіді:


129

Власне, згідно зі стандартом, constмодифікує елемент безпосередньо зліва від нього . Використання constна початку декларації - лише зручний розумовий ярлик. Отже, наступні два твердження еквівалентні:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

Для того, щоб переконатися, що сам вказівник не змінений, його constслід розміщувати після зірочки:

char * const constantPointerToMutableContent;

Щоб захистити як вказівник, так і вміст, на який він вказує, використовуйте два consts.

char const * const constantPointerToConstantContent;

Я особисто прийняв рішення, щоб завжди ставити const після тієї частини, яку я не збираюсь модифікувати, щоб я зберігав узгодженість, навіть коли вказівник - це та частина, яку я хочу постійно підтримувати.


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"

[Щоб запам’ятати це, ось просте правило, „*“ впливає спочатку на весь LHS ]


Гаразд, зараз зрозумів. Дуже дякую.
Luchian Grigore

1
unmutable pointer to char*.Це незмінний вказівник, що вказує на charnot char *.
Алок Зберегти

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

Якщо під "вказівником константи змінної" ви маєте на увазі "вказівник константи", то ви прибили його, брате!
Lino Mediavilla

Ну в (5) це змінний вказівник на постійний вказівник на константу char просто тому, що праворуч від останньої зірочки перед ідентифікатором "x" немає "const". Але в (6) це стає постійним покажчиком, решта залишається незмінною.
Lino Mediavilla
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.