2011-10-27 9 views
38

Co oznacza const w kwalifikatorze "najwyższego poziomu" w C++?Co to są kwalifikatory const na najwyższym poziomie?

A jakie są inne poziomy?

Na przykład

int const *i; 
int *const i; 
int const *const i; 
+3

Przykłady, proszę? – bmargulies

+0

Nie wiem, co masz na myśli przez przykłady, ale dodałem pewne kwalifikatory const, które znam. – user103214

+3

Zobacz także [Gdzie jest definicja "kwalifikatorów cv najwyższego poziomu" w standardzie C++ 11?] (Http://stackoverflow.com/q/24676824/1708801) –

Odpowiedz

49

najwyższego poziomu const kwalifikator dotyczy samego obiektu. Inne są tylko istotne ze wskaźnikami i referencjami. Nie powodują one, że obiekt staje się stały i tylko uniemożliwiają modyfikację poprzez ścieżkę za pomocą wskaźnika lub odwołania o wartości wskaźnika lub . Tak więc:

char x; 
char const* p = &x; 

To nie jest stała najwyższego poziomu i żaden z obiektów nie jest niezmienny. Wyrażenia *p nie można używać do modyfikowania x, ale mogą być inne wyrażenia ; x nie jest const. W związku z tym

*const_cast<char*>(p) = 't' 

jest legalne i dobrze zdefiniowane.

Ale

char const x = 't'; 
char const* p = &x; 

Tym razem jest const na x najwyższego poziomu, więc x jest niezmienna. Żadne wyrażenie nie może go zmienić (nawet jeśli użyto const_cast). Kompilator może umieścić x w pamięci tylko do odczytu i może przyjąć, że wartość nigdy nie ulegnie zmianie, niezależnie od tego, co może zrobić inny kod.

Aby dać wskaźnik najwyższego poziomu const, można napisać:

char x = 't'; 
char *const p = &x; 

W tym przypadku p wskaże x zawsze; każda próba zmiany tego jest niezdefiniowanym zachowaniem (i kompilator może umieścić p w pamięci tylko do odczytu, lub przyjąć, że *p odnosi się do x, niezależnie od jakiegokolwiek innego kodu).

+3

Bardzo jasne, dziękuję :) – Seb

+6

Jeszcze jeden punkt: podczas pisania funkcji odrzucane są kwalifikatory najwyższego poziomu argumentów. Oznacza to, że 'void foo (char const)' i 'void foo (char)' są tą samą funkcją (i w rzeczywistości mogą być wymieniane). Rozumowanie jest takie, że ponieważ argument jest brany za pomocą kopii, osoba dzwoniąca nie dba o to, czy kopię można zmodyfikować, czy nie, więc jest ona dla niej przejrzysta. –

+7

@ MatthieuM. Dobra rada, choć nie do końca prawdziwa, jak stwierdzono. Kwalifikatory najwyższego poziomu są ignorowane w deklaracji oraz w typie funkcji. W definicji jednak nadal zachowują się jak zwykle w ramach funkcji. (Kwalifikatory najwyższego poziomu są również ignorowane przez parametry "typid" i szablonu, przy dopasowywaniu wyjątków do przechwytywania i prawdopodobnie w niektórych innych przypadkach, o których zapomniałem.) W praktyce nie mają one również wpływu na wartości zwracane poza klasą.) –

10

int *const i stawia const na najwyższym poziomie, natomiast int const *i nie.

Pierwsza mówi, że sam wskaźnik i jest niezmienny, podczas gdy drugi mówi, że pamięć wskazywana przez wskaźnik jest niezmienna.

Zawsze, gdy const pojawia się bezpośrednio przed typem lub po nim, jest to kwalifikator najwyższego poziomu.

+0

Doskonała i jasna odpowiedź. P.S. 'int const * i' jest równe' const int * i' (wszystkie są const niskiego poziomu). Używam 'const int * i' (low-level), aby odróżnić jego poziom const częściej od' int * const i' (najwyższego poziomu). – dotslash

5

Jak to zostało wyjaśnione do mnie, biorąc pod uwagę:

[const] TYPE * [const] VARIABLE 

ZMIENNA jest stosowany aby wskazać danych typu TYP przez *VARIABLE

narysować linię przez * lub wielokrotny * s

  1. Jeśli istnieje const do lewo z * ona zastosowanie do danych oraz danych nie mogą być zmienione: *VARIABLE nie można przypisać, z wyjątkiem przy inicjalizacji
  2. Jeśli istnieje const do prawo z * stosuje względem ZMIENNA i jakie ZMIENNE punkty nie mogą być zmieniane: VARIABLE nie można przypisać, z wyjątkiem initiali zacji

Więc:

  |    left right 
int  *  i1; 
      |    no no  can change *i1 and i1 

int const *  i2;  
      |    yes no  cannot change *i2 but can change i2 

int  * const i3; 
      |    no yes can change *i3 but i3 cannot be changed 

int const * const i4; 
      |    yes yes cannot change *i4 or i4 
+0

'const' wiąże się po lewej stronie. chyba że nie ma nic po lewej stronie, to wiąże się z prawej strony – sp2danny