const char * i char const * - czy są takie same?

81

Z mojego punktu widzenia constmodyfikatory należy czytać od prawej do lewej. Z tego wynika, że:

const char*

jest wskaźnikiem, którego elementy char nie mogą być modyfikowane, ale sam wskaźnik może, a

char const*

jest stałym wskaźnikiem do mutableznaków.

Ale otrzymuję następujące błędy dla następującego kodu:

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

Więc ... który to jest? Czy moje rozumienie lub kompilator (VS 2005) są błędne?

Luchian Grigore
źródło
35
W razie wątpliwości zawsze używaj reguły spiralnej .
Alok Save
„… których elementy char można modyfikować, ale sam wskaźnik może, i…” - myślę, że chciałeś powiedzieć „nie można” dla jednego z tych elementów „można”, ale nie wiem jak jesteś zdezorientowany, więc nie wiem, co poprawić: P
detly
1
Wypróbuj tę witrynę internetową: www.cdecl.org
yasouser
Kompilator nigdy się nie myli;)
monolit

Odpowiedzi:

129

Właściwie zgodnie ze standardem constmodyfikuje element bezpośrednio po jego lewej stronie . Użycie constna początku deklaracji jest po prostu wygodnym skrótem myślowym. Zatem następujące dwie instrukcje są równoważne:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

Aby zapewnić, że sam wskaźnik nie zostanie zmodyfikowany, constnależy umieścić go po gwiazdce:

char * const constantPointerToMutableContent;

Aby chronić zarówno wskaźnik, jak i zawartość, na którą wskazuje, użyj dwóch stałych.

char const * const constantPointerToConstantContent;

Osobiście przyjąłem zawsze umieszczanie stałej po części, której nie zamierzam modyfikować, w taki sposób, aby zachować spójność, nawet gdy wskaźnik jest częścią, którą chcę zachować na stałym poziomie.

Greyson
źródło
23
„wygodny skrót” to ciekawy opis czegoś, co nie jest krótsze i nie jest zgodne z normalnymi zasadami.
beetstra
Standard nie ma znaczenia, jakiej kolejności używasz. Sekcja 7.1.6 pokazuje tylko oba miejsca i mówi, że używaj ich tylko w jednym.
edA-qa mort-ora-y 11.11.11
1
@beetstra Zgadzam się. Zmieniłem to na „wygodny skrót myślowy”, żeby był bardziej czytelny.
Greyson
31

Działa, ponieważ oba są takie same. Możesz być w tym zdezorientowany,

const char*  // both are same
char const*

i

char* const  // unmutable pointer to "char"

i

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

[Aby to zapamiętać, oto prosta reguła: „*” wpływa najpierw na cały jego LHS ]

iammilind
źródło
Ok, teraz rozumiem. Wielkie dzięki.
Luchian Grigore
1
unmutable pointer to char*Jest to niezmienny wskaźnik wskazujący na charnie char *.
Alok Save
25

Dzieje się tak, ponieważ zasada brzmi:

ZASADA: constwiąże w lewo, chyba że nic nie ma po lewej stronie, wtedy wiąże się z prawej :)

więc spójrz na te jako:

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

oba takie same! och, i --->>i <<---NIE są operatorami, po prostu pokazują, do czego są constprzypisane.

Akanksh
źródło
2
tak, prawidłowy operator jest -->>i działa tylko na wartościach. Spróbuj int i = 8; std::cout << (i -->> 1) << std::endl;:)
Alexander Malakhov,
11

(z 2 prostych pytań inicjalizacyjnych zmiennych )

Naprawdę dobra zasada dotycząca const:

Przeczytaj deklaracje od prawej do lewej.

(zobacz Vandevoorde / Josutiss „Szablony C ++: kompletny przewodnik”)

Na przykład:

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.

Odkąd stosuję się do tej praktycznej zasady, nigdy więcej nie zinterpretowałem błędnie takich deklaracji.

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

Sebastian Mach
źródło
+1 To fantastyczne, dziękuję! Od wieków próbowałem sobie poradzić z takimi rzeczami, jak const char* consti dzięki tobie teraz to rozumiem.
OMGtechy
5

Oto jak zawsze staram się interpretować:

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`".

Mam nadzieję, że to pomoże!

yasouser
źródło
0

W obu przypadkach wskazujesz na stały znak.

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?

Domyślnie constma zastosowanie do tego, co znajduje się bezpośrednio po lewej stronie, ale może mieć zastosowanie do tego, co znajduje się bezpośrednio po jego prawej stronie, jeśli nic go nie poprzedza, jak w (1).

Lino Mediavilla
źródło
Ostatni: wskaźnik do stałej zmiennej, do stałego wskaźnika, do stałego znaku.
Secko
Jeśli przez „stały wskaźnik zmiennej” masz na myśli „stały wskaźnik”, to udało ci się to, stary!
Lino Mediavilla
No cóż, w (5) jest to zmienny wskaźnik do stałego wskaźnika do stałego znaku po prostu dlatego, że nie ma „const” po prawej stronie ostatniej gwiazdki przed identyfikatorem „x”. Ale w (6) to staje się stałym wskaźnikiem, reszta pozostaje taka sama.
Lino Mediavilla