C ++: odwołanie do const, przed i po specyfikatorze typu

144

Jaka jest różnica między argumentami w:

int foo1(const Fred &arg) {
...
}

i

int foo2(Fred const &arg) {
...
}

? Nie widzę tego przypadku w FAQ parashift.

eisbaw
źródło
2
czy to jest kwestia stylu? „const Fred” brzmi dobrze po angielsku, ale „Fred const” wygląda lepiej.
LatinSuD
1
Na powiązana uwaga jest jakiś powód, trzeba wolą Fred const &argponad Fred const& arg? To drugie podoba mi się bardziej, ponieważ const&jest tam jednostka oznaczająca „constref”, a nazwa argjest oddzielona spacją od wszystkich specyfikatorów typu.
Frank
4
@dehmann: Ale nie int const& refmam na myśli „const ref”, ale „ref to const”.
Cedric H.
1
Duplikat: stackoverflow.com/questions/2640446/…
Michael Aaron Safyan

Odpowiedzi:

112

Nie ma różnicy, ponieważ const jest odczytywane od prawej do lewej w odniesieniu do &, więc oba reprezentują odwołanie do niezmiennej instancji Fred.

Fred& constoznaczałoby, że samo odniesienie jest niezmienne, co jest zbędne ; gdy mamy do czynienia ze wskaźnikami const, oba Fred const*i Fred* constsą ważne, ale różne.

To kwestia stylu, ale wolę używać constjako przyrostka, ponieważ można go stosować konsekwentnie, w tym funkcje składowe const .

Sean Fausett
źródło
Więc co to punkt, aby std::is_const<const T&>::valuebyć false?
otchłań. 7
@ abyss.7 to odniesienie do const T; odniesienie jest zmienne.
Sean Fausett
125

Zachowanie

Nie ma semantycznej różnicy między const T&i T const&; język traktuje je jako ten sam typ. (To samo dotyczy const T*iT const* .)

Kwestia stylu

Jeśli chodzi o to, co powinieneś preferować stylistycznie, odmówię od wielu innych odpowiedzi i wolę const T&(i const T*):

  • const T&jest stylem używanym w książce Stroustrupa The C ++ Programming Language .
  • const T& jest stylem używanym w samym standardzie C ++.
  • const T*jest stylem używanym w książce K&R The C Programming Language .
  • const T* to styl używany w standardzie C.
  • Ze względu na powyższe czynniki myślę const T&/ const T*mam znacznie większą bezwładność niż T const&/ T const*. const T&/ const T*empirycznie wydaje mi się o wiele bardziej powszechne niż T const&/ T const*w całym kodzie C ++ i C, które widziałem. Myślę, że przestrzeganie typowych praktyk jest bardziej czytelne niż dogmatyczne przestrzeganie reguł analizy od prawej do lewej.
  • Dzięki T const*temu łatwiej jest zgubić *as T* const(zwłaszcza jeśli ludzie nie są do tego tak przyzwyczajeni). Z drugiej strony const* Tnie jest to legalna składnia.

A co z regułą analizy od prawej do lewej?

Odnośnie całego argumentu analizy od prawej do lewej, którego ludzie lubią używać: jak wspomniałem w komentarzu do innej odpowiedzi, const T&dobrze czyta się również od prawej do lewej. To odniesienie do stałej T. „T” i „stała” mogą działać jako przymiotnik lub rzeczownik. (Ponadto odczyt od T const*prawej do lewej może być niejednoznaczny, ponieważ może być nieprawidłowo zinterpretowany jako „wskaźnik stałej do T” zamiast „wskaźnika do stałej T”).

jamesdlin
źródło
3
+1, uzgodniono. Czytając kod, łatwiej jest dostrzec stałą, jeśli linia zaczyna się od const. Reguła prawa-lewa jest naprawdę potrzebna tylko podczas ręcznego analizowania deklaracji typu włochatego. Dlaczego nie zoptymalizować pod kątem najczęstszego przypadku? Poza tym IMHO, jeśli piszesz deklaracje typu, więc musisz ręcznie uruchomić FSM w swojej głowie, robisz to źle.
Andreas Magnusson
2
-1. Bez względu na to, jak uzasadnione są Twoje wnioski i na ile osobiście się z nimi zgadzam, nie odpowiadają one wprost na zadane pytanie . To sprawia, że ​​druga w kolejności odpowiedź na proste pytanie wydaje się być bełkotem niezwiązanym z tematem na temat jakiejś brudnej podwodnej maszyny, bez wniosków, bez bezpośredniej odpowiedzi - nic. Otrzymasz moje głosy za, gdy dodasz proste, jasne podsumowanie stwierdzające: „ Nie, nie ma semantycznej różnicy między obiema składniami , ale są pewne kwestie stylistyczne, jak następuje…”. I dopiero wtedy te wszystkie kule.
ulidtko
1
IMO powód const T&brzmi lepiej: 1- Czytamy kod od lewej do prawej. I 2 - Opisując nową koncepcję, zaczynamy od koncepcji bardziej ogólnej do bardziej szczegółowej. Tutaj constsłowo kluczowe jest bardziej ogólne, ponieważ dzieli zmienną przestrzeń na dwie kategorie, podczas gdy specyfikator typu dzieli ją na wiele.
pooya13
„wskaźnik do” powinien pozostać razem. Więc nie ma dwuznaczności dlaT const*
Dexter
13

Chociaż są jednym i tym samym, aby zachować spójność z regułą PRAWO-LEWO dotyczącą analizowania deklaracji C i C ++, lepiej jest pisaćFred const &arg

Odnieś się również do tego, aby lepiej zrozumieć deklaracje, kwalifikatory i deklaratory.

Chubsdad
źródło
1
Wolę przyrostek, ponieważ działa lepiej z typedefekspansją. Przykład: typedef int* pointer;, const pointer nie jest const int* , to jest int* const. Forma sufiksu nie jest niezręczna.
Matthieu M.,
4
IMO const T&czyta również dobrze od prawej do lewej; jest to odniesienie do stałej T. Ti constantkażdy może działać jako przymiotnik lub rzeczownik.
jamesdlin
7

Obie działają, a tutaj jest wyjaśnienie od człowieka, który to napisał.
Cytując go:

Czemu? Kiedy wymyśliłem "const" (początkowo nazwane "readonly" i odpowiadające mu "writeonly"), pozwoliłem mu występować przed lub po typie, ponieważ mogłem to zrobić bez dwuznaczności.

Domyślna
źródło
3

Referencje nie działają tak samo jak wskaźniki: dla wskaźników możesz mieć „stałe wskaźniki” ( type * const p) i „wskaźnik do stałej” ( const type * plub type const * p).

Ale nie masz tego dla odniesień: odniesienie zawsze będzie odnosić się do tego samego obiektu; w tym sensie możesz uznać, że „referencje” są „stałymi referencjami” (tak samo, jak można mieć „stałe wskaźniki”).

Dlatego coś w rodzaju „type & const ref” jest niedozwolone. Możesz mieć tylko `` odniesienie do typu '' ( type &ref) i `` odniesienie do stałego typu '' ( const type &reflubtype const &ref ; oba są dokładnie równoważne).

I ostatnia rzecz: nawet jeśli const typebrzmi bardziej poprawnie w języku angielskim, pisanie type constpozwala na bardziej systematyczne rozumienie deklaracji „od prawej do lewej”: int const & refmożna odczytać ma „ref jest odniesieniem do stałej int”. Lub bardziej skomplikowany przykład int const * const & ref:, ref jest odniesieniem do stałego wskaźnika do stałej int.

Wniosek: w twoim pytaniu oba są dokładnie równoważne.

Cedric H.
źródło