a hihetetlen Const referencia, amely nem Const
miközben a NamedType könyvtáron dolgoztam, találkoztam egy olyan helyzettel, amely zavarba ejtett: egy const referencia, amely lehetővé teszi a hivatkozott objektum módosítását. const_cast
nélkül. mutable
nélkül. Anélkül, hogy bármi fel a hüvely.
hogyan lehet ez? És hogyan lehet érvényesíteni a const
értéket ebben a const hivatkozásban?
egy const hivatkozás, amely nem const
itt van egy leírás egy olyan helyzetről, amikor ez a furcsa hivatkozás felmerül. Vegye figyelembe a következő burkolóosztályt:
template<typename T>class Wrapper{public: Wrapper(T const& value) : value_(value) {} T const& get() const { return value_; } private: T value_;};
ez a Wrapper
osztály tárolja a T
típusú értéket, és hozzáférést biztosít a get()
módszerrel (ettől függetlenül, ha kíváncsi vagy, hogy a “get” jó név-e, érdemes elolvasni ezt a részletes vitát). Fontos, hogy a get()
metódus csak olvasható hozzáférést biztosít a tárolt értékhez, mert const hivatkozást ad vissza.
ennek ellenőrzéséhez példányosítsuk a sablont például int
– vel. A tárolt érték get()
metódussal történő módosítása sikertelen (próbálja meg kattintani a Futtatás gombra).
ami nagyon jó, mert azt akarjuk, hogy a get()
csak olvasható legyen.
de most példányosítsuk a Wrapper
– t int&
– vel. Ennek egyik felhasználási módja lehet például a másolat elkerülése vagy a a
lehetséges módosításainak nyomon követése. Most próbáljuk meg módosítani a tárolt értéket a get()
által visszaadott const hivatkozáson keresztül:
és ha megnyomod a gombot, látni fogod, hogy… összeáll! És kiírja a const hivatkozáson keresztül módosított értéket, mintha semmi különös nem történt volna.
hát nem érthetetlen? Nem érzi, hogy a const
által nyújtott biztonság megnyugtató benyomása összeomlik körülöttünk? Kiben bízhatunk?
próbáljuk megérteni, mi történik ezzel a hivatkozással.
Const hivatkozás vagy hivatkozás a const-ra?
a lényeg az, hogy az a referenciánk egy const referencia, de nem hivatkozás a const-ra.
hogy aláhúzzuk, mit jelent ez, bontsuk le lépésről lépésre, mi történik a sablon példányában.
a get()
metódus const T&
értéket ad vissza, a T
a template T
– ből származik. Második esetünkben a T
int&
, tehát a const T&
const (int&) &
.
nézzük meg közelebbről ezt a const (int&)
– et. A int&
egy hivatkozás, amely int
– re utal, és módosíthatja azt a int
– et. De a const (int&)
egy int&
hivatkozás, azaz const
, ami azt jelenti, hogy maga a hivatkozás nem módosítható.
mit jelent egy hivatkozás módosítása? Elméletileg azt jelentené, hogy egy másik tárgyra utal, vagy nem utal semmire. De mindkét lehetőség illegális A C++ – ban: a referencia nem tud újracsatolni. Ugyanarra a tárgyra utal az egész élete során.
tehát a const
nem sokat mond referenciaként, mivel mindig const
, mivel nem tudnak újracsatolni. Ez azt jelenti, hogy a const (int&)
gyakorlatilag ugyanolyan típusú, mint a int&
.
ami azt jelenti, hogy get()
visszatér (int&) &
. A referenciák szabályai szerint ez int&
.
tehát a get
egy int&
értéket ad vissza. A kezelőfelülete T const&
, de valójában int&
. Nem igazán kifejező kód, ugye?
hogyan lehet a const hivatkozást hivatkozássá tenni a const-ra
most, hogy már túl vagyunk a probléma megértésének első lépésén, hogyan javíthatjuk meg? Vagyis hogyan tehetjük vissza a get()
hivatkozást a tárolt értékre, amely nem teszi lehetővé annak módosítását?
ennek egyik módja a const
kifejezett beszúrása a hivatkozásba. Ezt úgy tehetjük meg, hogy levesszük a hivatkozást, hozzáadunk egy const
értéket, és visszahelyezzük a hivatkozást. A hivatkozás eltávolításához a std::remove_reference
– et használjuk a C++11-ben, vagy a kényelmesebb std::remove_reference_t
– t a C-ben++14:
amint láthatja, ha a Futtatás gombra kattint, a várható fordítási hiba Most megjelenik, amikor megpróbálja módosítani a Wrapper
– ben tárolt értéket.
azt hiszem, hasznos megérteni, hogy mi történik ezzel a hivatkozással, mert ez a kód úgy néz ki, mintha biztonságos lenne, de valójában nem, és ez a legveszélyesebb fajta.
az oldalba ágyazott fenti játszóterek kódjával játszhatsz. Nagy köszönet a rakete1111 stack overflow felhasználónak, hogy segített megérteni a probléma okait.
Ön is kedvelheti
- a leginkább bosszantó elemzés: hogyan lehet észrevenni és gyorsan megjavítani