Koks skirtumas tarp const int *, const int * const ir int const *?

Aš visada sugadinau, kaip tinkamai naudoti const int* , const int * const ir int const * . Ar yra taisyklių, apibrėžiančių, ką galite ir ko negalite padaryti?

Noriu žinoti viską, ką reikia padaryti, ir visa tai nesusijusi su užduotimis, funkcijų perdavimu ir tt

1116
17 июля '09 в 16:28 2009-07-17 16:28 ultraman yra nustatytas liepos 17 d ., 09:28, 2009-07-17 16:28
@ 15 atsakymų

Skaitykite jį atgal (kaip valdoma pagal laikrodžio rodyklę / spiralę ):

  • int* - rodyklė į int
  • int const * - rodyklė į const int
  • int * const - const rodyklė į int
  • int const * const - const rodyklė į const int

Dabar pirmasis const gali būti bet kurioje tokio tipo pusėje:

  • const int * == int const *
  • const int * const == int const * const

Jei norite išprotėti, galite tai padaryti:

  • int ** - rodyklė į rodyklę į int
  • int ** const - žymeklis į rodyklę į int
  • int * const * - žymeklis į rodyklę const iki int
  • int const ** - rodyklė link rod int
  • int * const * const - pointer const link po int
  • ...

Ir įsitikinkite, kad mes aiškiai suprantame const

 const int* foo; int *const bar; //note, you actually need to set the pointer //here because you can't change it later ;) 

foo yra kintamas rodyklė į pastovų sveikąjį skaičių. Tai leidžia jums pakeisti tai, ką nurodėte, bet ne vertę, kurią nurodote. Tai dažniausiai matoma C stiliaus eilutėse, kuriose yra rodyklė į const char . Galite pakeisti liniją, į kurią nukreipiate, bet negalite pakeisti šių linijų turinio. Tai svarbu, kai pati eilutė yra programos duomenų segmente ir neturėtų būti keičiama.

bar yra fiksuotas arba fiksuotas rodiklis prie vertės, kurią galima keisti. Tai tarsi nuoroda be papildomo sintaksės cukraus. Dėl šios priežasties paprastai naudosite nuorodą, kurioje naudosite T* const rodiklį, jei jums nereikia NULL rodyklių.

1896 m
17 июля '09 в 16:29 2009-07-17 16:29 Atsakymą pateikė Matt Price liepos 17 d., 09:29, 2009-07-17 16:29

Tiems, kurie nežino apie laikrodžio rodyklę / spiralės taisyklę: Pradėkite nuo kintamojo pavadinimo, perkelkite jį pagal laikrodžio rodyklę (šiuo atveju perkelkite atgal) į kitą rodyklę arba . Pakartokite iki išraiškos pabaigos.

Čia yra demo versija:

2019

269
10 июля '15 в 5:15 2015-07-10 05:15 atsakymas duotas „ Shijing Lv“ liepos 15 d. 15:15, 2015-07-10 05:15

Manau, kad čia viskas buvo pasakyta, bet tik noriu pridurti, kad turėtumėte saugoti typedef ! Tai ne tik teksto pakeitimas.

Pavyzdžiui:

 typedef char *ASTRING; const ASTRING astring; 

astring tipas yra char * const , o ne const char * . Tai yra viena iš priežasčių, kodėl aš visada būsiu linkęs į tipo teisę ir niekada nepradėsiu.

129
17 июля '09 в 16:39 2009-07-17 16:39 atsakymą įteikė Kaz Dragon , liepos 17 d., 09:39, 2009-07-17 16:39

Kaip ir daugelis, visi pažymėjo:

Koks yra skirtumas tarp const X* p , X* const p ir const X* const p ?

Jūs turite perskaityti rodyklės deklaracijas iš dešinės į kairę.

  • const X* p reiškia, kad "p taškai į X, kuris yra const": X objektas negali būti pakeistas p.

  • X* const p reiškia, kad "p yra rodyklė į X, o tai nėra konstanta": rodyklę p negalite pakeisti, tačiau galite pakeisti objektą X per p.

  • const X* const p reiškia, kad „p yra rodyklė į X konstanta, kuri yra const“: rodyklę p negalite pakeisti patys, o objekto X - p.

47
17 июля '09 в 16:36 2009-07-17 16:36 atsakymą luke pateikė liepos 17 d . 09:16 16:36 2009-07-17 16:36
  • Nuolatinė nuoroda:

    Nuoroda į kintamąjį (čia, int), kuri yra pastovi. Mes perduodame kintamąjį kaip nuorodą daugiausia dėl to, kad nuorodos yra mažesnės nei faktinė vertė, tačiau yra šalutinis poveikis, ir tai yra todėl, kad jis atrodo kaip faktinio kintamojo pseudonimas. Mes galime netyčia keisti pagrindinį kintamąjį per visą mūsų prieigą prie slapyvardžio, todėl mes nuolat jį pakeisime, kad išvengtume šio šalutinio poveikio.

     int var0 = 0; const int  = var0; ptr1 = 8; // Error var0 = 6; // OK 
  • Nuolatiniai rodikliai

    Kai pastovus žymeklis nurodo kintamąjį, jis negali nukreipti į kitą kintamąjį.

     int var1 = 1; int var2 = 0; int *const ptr2 =  ptr2 =  // Error 
  • Rodyklė į pastovią

    Rodyklė, per kurią negalite keisti rodomo kintamojo vertės, vadinamas rodikliu į konstanta.

     int const * ptr3 =  *ptr3 = 4; // Error 
  • Nuolatinis rodiklis pastoviam

    Nuolatinis rodyklė į pastovumą yra rodyklė, kuri negali pakeisti adreso, į kurį jis nurodo, ir nekeičia toje vietoje išsaugotos vertės.

     int var3 = 0; int var4 = 0; const int * const ptr4 =  *ptr4 = 1; // Error ptr4 =  // Error 
41
17 мая '14 в 23:21 2014-05-17 23:21 atsakymą pateikė Behrooz Tabesh gegužės 17, 14, 23:21 2014-05-17 23:21

Šis klausimas parodo, kodėl aš norėčiau daryti tai, ką minėjau savo klausime yra pastovus po galiojančio tipo identifikatoriaus? p>

Trumpai tariant, manau, kad paprasčiausias būdas prisiminti taisyklę yra tai, kad „const“ seka tai, ką ji nurodo. Todėl jūsų klausime „int const *“ reiškia, kad int yra konstanta, o „int * const“ reiškia, kad rodyklė yra pastovi.

Jei kas nors nusprendžia jį iškelti (pvz., „Const int *“), kaip ypatingą išimtį šiuo atveju jis taikomas objektui po jo.

Daugelis žmonių mėgsta naudoti šią ypatingą išimtį, nes mano, kad tai atrodo geriau. Man tai nepatinka, nes tai yra išimtis ir taip painiojami dalykai.

16
17 июля '09 в 16:52 2009-07-17 16:52 atsakymas pateikiamas TED liepos 17 d. 09:16 16:52 2009-07-17 16:52

Bendra taisyklė yra ta, kad „ const raktinis žodis taikomas tai, kas prieš tai iš karto. Išimtis yra pradinė const .

  • const int* atitinka int const* ir reiškia "rodyklę į int konstanta" .
  • const int* const rungtynės int const* const ir reiškia "pastovus žymeklis į int konstanta" .

Redaguoti: jei „Dos“ ir „Don'ts“ nepakanka, ar galėtumėte paaiškinti, ką norite?

15
17 июля '09 в 16:30 2009-07-17 16:30 Atsakymą pateikė „ AProgrammer “ liepos 17 d. 09.30 val. 2009-07-17 16:30

Paprastas naudojimas „const

Paprasčiausias būdas yra paskelbti pavadintą konstanta. Norėdami tai padaryti, deklaruokite konstanta, lyg ji būtų kintamasis, bet pridėkite jį priešais jį. Turite nedelsiant jį inicijuoti konstruktoriuje, nes, žinoma, jūs negalite nustatyti vertės vėliau, nes tai pakeis. Pavyzdžiui

 const int Constant1=96; 

sukurs sveikasis skaičius, pastoviai vadinamas „Constant1“, kurio vertė 96.

Tokios konstantos yra naudingos programoje naudojamiems parametrams, tačiau jų nereikia keisti po programos sudarymo. Jis turi pranašumą programuotojams per „išankstinio apdorojimo“ #define komandą, nes jį supranta ir naudoja pats kompiliatorius, o ne tik jį pakeitė programos tekstas, prieš tai pasiekdamas pagrindinį kompiliatorių, todėl klaidų pranešimai yra daug naudingesni.

Jis taip pat veikia su rodikliais, bet jūs turite būti atsargūs, kai const nustato, ar rodyklė, ar tai, ką ji nurodo, yra pastovi, arba abu. Pavyzdžiui

 const int * Constant2 

deklaruoja, kad Constant2 yra kintamasis rodiklis pastoviam sveikam skaičiui ir

 int const * Constant2 

- alternatyvi sintaksė, kuri daro tą patį, o

 int * const Constant3 

praneša, kad Constant3 yra nuolatinis rodiklis kintamam skaičiui ir

 int const * const Constant4 

deklaruoja, kad konstanta4 yra pastovus rodiklis pastoviam sveikam skaičiui. Iš esmės, „const“ reiškia tai, kas yra jos kairėje pusėje (išskyrus atvejus, kai jame nėra nieko, šiuo atveju tai reiškia viską, kas yra jos tiesioginė teisė).

nuoroda: http://duramecho.com/ComputerInformation/WhyHowCppConst.html

14
17 июля '09 в 16:31 2009-07-17 16:31 atsakymas pateikiamas ufukgun liepos 17 d., 09:31, 2009-07-17 16:31

Turėjau tas pačias abejones, kaip ir jūs, kol susitikau su šia knyga iš C ++ Guru Scott Meyers. Žr. Šios knygos trečiąją pastraipą, kurioje jis išsamiai kalba apie const .

Tiesiog atlikite šį patarimą.

  • Jei žvaigždute rodomas žodis const rodomas kaip konstanta.
  • Jei žvaigždė dešinėje pusėje rodomas žodis const , rodyklė yra pastovi.
  • Jei const pasirodo abiejose pusėse, abi jos yra nuolatinės.
7
21 марта '15 в 16:56 2015-03-21 16:56 atsakymas pateikiamas rgk kovo 21 d., 15 val. 16:56 2015-03-21 16:56

C ++ sistemoje yra daug kitų subtilių taškų, susijusių su const teisingumu. Darau prielaidą, kad čia pateiktas klausimas yra tik C, bet pateiksiu keletą susijusių pavyzdžių, nes C + + žyma:

  • Dažnai perduodate didelius argumentus, pvz., Eilutes, pvz., TYPE const > , kurios neleidžia jums keisti ar kopijuoti objekto. Pavyzdys:

    TYPE TYPE::operator=(const TYPE { ... return *this; }

    Tačiau TYPE const neturi prasmės, nes nuorodos visada yra const.

  • Visada turėtumėte nurodyti klasės metodus, kurie nekeičia klasės kaip const , kitaip negalite skambinti metodu iš TYPE const > . Pavyzdys:

    bool TYPE::operator==(const TYPE const { ... }

  • Yra bendrų situacijų, kai grąžinimo vertė ir metodas turi būti const. Pavyzdys:

    const TYPE TYPE::operator+(const TYPE const { ... }

    Tiesą sakant, const metodai neturėtų grąžinti vidinių klasės duomenų kaip nuorodos į non-const.

  • Todėl dažnai reikia sukurti ir konst., Ir nestandartinį metodą, naudojant const perkrovą. Pavyzdžiui, jei apibrėžiate T const operator[] (unsigned i) const; , tada tikriausiai reikės ir nenuolatinės versijos:

    inline T operator[] (unsigned i) { return const_cast<char static_cast<const TYPE ); }

„Afaik“ C sistemoje nėra jokių funkcijų, ne narių funkcijos negali būti „C ++“, const metodai gali turėti šalutinį poveikį, o kompiliatorius negali naudoti const funkcijų, kad būtų išvengta funkcijų skambučių dubliavimo. Tiesą sakant, net paprasta nuoroda int const > gali reikšti, kad vertė, su kuria ji susijusi, bus pakeista kitur.

5
13 сент. Jeff Burdges atsakymas, pateiktas rugsėjo 13 d 2011-09-13 13:50 '11, 13:50, 2011-09-13 13:50

Tai paprasta, bet sunku. Atkreipkite dėmesį, kad galime pakeisti „ const kvalifikaciją į bet kurį duomenų tipą ( int , char , float ir tt).

Žr. Toliau pateiktus pavyzdžius.


const int *p ==> *p yra tik skaityti [ p yra rodyklė į pastovų sveikąjį skaičių]

int const *p ==> *p yra tik skaitymui [ p yra rodiklis pastoviam sveikam skaičiui]


int *p const ==> Neteisingas pareiškimas. Kompiliatorius sukuria sintaksės klaidą.

int *const p ==> p tik skaitomas [ p yra pastovus rodiklis sveikam skaičiui]. Kadangi p rodyklė yra tik skaityti čia, deklaracija ir apibrėžimas turėtų būti toje pačioje vietoje.


const int *p const ==> Neteisingas pareiškimas. Kompiliatorius sukuria sintaksės klaidą.

const int const *p ==> *p tik skaitomas

const int *const p1 ==> *p ir p yra tik skaitomi [ p yra pastovus rodiklis pastoviam sveikam skaičiui]. Kadangi p rodyklė yra tik skaityti čia, deklaracija ir apibrėžimas turėtų būti toje pačioje vietoje.


int const *p const ==> Neteisingas pareiškimas. Kompiliatorius sukuria sintaksės klaidą.

int const int *p ==> Neteisingas pareiškimas. Kompiliatorius sukuria sintaksės klaidą.

int const const *p ==> *p yra tik skaitomas ir lygiavertis int const *p

int const *const p ==> *p ir p yra tik skaitomi [ p yra pastovus rodiklis pastoviam sveikam skaičiui]. Kadangi p rodyklė yra tik skaityti čia, deklaracija ir apibrėžimas turėtų būti toje pačioje vietoje.

5
04 янв. Atsakymas, kurį pateikė Abhijit Sahu Jan 04 2015-01-04 16:10 '15 at 16:10 2015-01-04 16:10

C ir C ++ deklaracijų sintaksė buvo pakartotinai apibūdinta kaip nepavykęs eksperimentas, originalūs dizaineriai.

Vietoj to įveskite pavadinimą „žymeklis į Type “; Aš jį Ptr_ :

 template< class Type > using Ptr_ = Type*; 

Dabar Ptr_<char> yra rodyklė į char .

Ptr_<const char> yra rodyklė į „ const char .

Ir const Ptr_<const char> yra const Ptr_<const char> rodyklė į const char .

Ten

2019

Atsakymą pateikė „ Cheers“ ir hth. 06 янв. - Alf 06 sausis 2016-01-06 03:12 '16 at 3:12 2016-01-06 03:12

Pastaba su abiejose pusėse esančiu int .

 const int *ptr=> 

arba

 int const *ptr=> 

const po '*' parodys pastovų rodyklę int .

 int *const ptr=> 

Tokiu atveju jie visi nukreipia į pastovų sveikąjį skaičių , tačiau nė vienas iš jų nėra nuolatinis rodiklis.

  const int *ptr1= *ptr2=> 

Tokiu atveju visi yra rodikliai į pastovų sveikąjį skaičių, o ptr2 yra pastovus rodiklis pastoviam sveikam skaičiui . Bet ptr1 nėra nuolatinis rodiklis.

 int const *ptr1= *const ptr2=> 
2
23 сент. Hunterio atsakymas, pateiktas rugsėjo 23 d 2018-09-23 11:44 '18, 11:44 2018-09-23 11:44

Tai daugiausia susiję su antra eilute: geriausia praktika, užduotys, funkcijų parametrai ir kt.

Bendroji praktika. Pabandykite padaryti visas const . Arba, kad tai atliktumėte kitaip, pradėkite nuo visų „ const , tada pašalinkite tiksliai būtinąjį const , reikalingą programai veikti. Tai bus didžiulė pagalba siekiant pasiekti konstatavimą ir padės užtikrinti, kad subtilios klaidos nebūtų įvestos, kai žmonės bando priskirti daiktus, kurių jie neturėtų keisti.

Venkite const_cast <> kaip maras. Tam yra vienas ar du teisiniai naudojimo būdai, tačiau jie yra labai mažai ir toli vienas nuo kito. Jei bandote pakeisti const objektą, tai bus daug geriau surasti tą, kuris jį paskelbė pirmą kartą, ir aptarti problemą su jais, kad būtų pasiektas sutarimas dėl to, kas turėtų vykti.

Tai labai patogiai veda į susitikimus. Jūs galite priskirti tik kažką, jei jis nėra const. Jei norite priskirti kažką, kas yra pastovus, žr. Aukščiau. Atminkite, kad deklaracijose int const *foo; ir int * const bar; įvairūs dalykai const - kiti atsakymai atspindi šią problemą labai gerai, taigi negaliu įeiti.

Funkcijų parametrai:

Naršyti pagal vertę: pvz. void func(int param) vis tiek ta pati, skambinimo svetainėje. Galima teigti, kad yra galimybių naudoti funkciją kaip void func(int const param) , tačiau tai neturi įtakos skambinančiajam, tik pačiai funkcijai, nes persiunčiama vertė per pokalbį negali būti pakeista.

Perkėlimas pagal nuorodą: pvz. void func(int > Dabar svarbu. Kai tik bus paskelbta, kad func gali keisti param , ir bet kuri skambinimo svetainė turi būti pasirengusi tvarkyti pasekmes. Pakeitus deklaraciją į void func(int const > keičiasi sutartis ir užtikrina, kad func negali pakeisti param , tai yra, kas yra perduodama. Kaip pastebėjo kiti, tai labai naudinga, jei norite perkelti didelį objektą, kurio nenorite keisti. Sertifikato perdavimas yra daug pigesnis nei didelių objektų perdavimas pagal vertę.

Praleisti rodyklę: pvz. void func(int *param) ir void func(int const *param) Šie du yra gana sinonimai su jų referencinėmis kopijomis, su sąlyga, kad iškviesta funkcija dabar turi patikrinti nullptr jei bet kuri kita sutartinė garantija negarantuoja, kad niekada nullptr in param .

Nuomonė šia tema. Tokiu atveju teisingumo įrodymas yra sunkiai sunkus, tiesiog per lengva padaryti klaidą. Taigi nullptr galimybių ir visada patikrinkite rodyklės parametrus nullptr . Atsikratysite skausmo ir kančių, o ilgainiui rasite klaidų. Kalbant apie patikrinimo kainą, jis yra pigus, o tais atvejais, kai į kompiliatorių įmontuota statinė analizė gali ją valdyti, optimizatorius vis tiek jį pašalins. Įjunkite laiko kodo kodą generuojant MSVC arba WOPR (manau) GCC, ir jūs jį gausite kaip programą kaip visumą, ty net skambinant funkcijoms, kurios kerta šaltinio kodo modulio ribą.

Dienos pabaigoje visa tai daro labai patikimu atveju, kai nuorodos į rodykles visada yra pirmenybės. Jie yra tik saugesni visoje vietoje.

1
15 марта '18 в 10:59 2018-03-15 10:59 atsakymas dgnuff pateikiamas kovo 15 d. 18 val. 10:59 2018-03-15 10:59

Man, const tai yra, ar ji rodoma kairėn ar dešinėn arba kairėn ir dešinėn, palyginti su * padeda suprasti tikrąją vertę.

  1. * LEFT of const reikšmė rodo, kad rodyklės nurodytas objektas yra const objektas.

  2. Dešinėje pusėje const rodo, kad rodyklė yra const rodiklis.

Toliau pateikta lentelė paimta iš standartinio standarto C ++ standarto programavimo kursų skaitytuvo Stanford CS106L.

2019

04 февр. atsakymas pateikiamas srivatsahc 04 vasaris 2019-02-04 10:48 '19 at 10:48 2019-02-04 10:48

Kiti klausimai apie „ žymes arba Užduoti klausimą