Błędny formularz:
int &z = 12;
Poprawna forma:
int y;
int &r = y;
Pytanie :
Dlaczego pierwszy kod jest nieprawidłowy? Jakie jest „ znaczenie ” błędu w tytule?
Błędny formularz:
int &z = 12;
Poprawna forma:
int y;
int &r = y;
Pytanie :
Dlaczego pierwszy kod jest nieprawidłowy? Jakie jest „ znaczenie ” błędu w tytule?
(ostringstream() << "x=" << x).str()
Odpowiedzi:
C ++ 03 3.10 / 1 mówi: „Każde wyrażenie jest albo lwartością, albo rwartością”. Należy pamiętać, że wartość kontra wartość jest właściwością wyrażeń, a nie przedmiotów.
Lvalues nazywają obiekty, które pozostają poza jednym wyrażeniem. Na przykład obj
, *ptr
, ptr[index]
, i ++x
są lwartościami.
Wartości R to wartości tymczasowe, które wyparowują na końcu pełnego wyrażenia, w którym żyją („w średniku”). Na przykład 1729
, x + y
, std::string("meow")
, i x++
są rvalues.
Operator address-of wymaga, aby jego „operand był l-wartością”. gdybyśmy mogli wziąć adres jednego wyrażenia, wyrażenie jest lwartością, w przeciwnym razie jest to rwartość.
&obj; // valid
&12; //invalid
int & = 12;
jest nieprawidłowe, standard mówi, że literał łańcuchowy to lwartość, a inne literały to rwartości.
std::string("meow")
tworzy się obiekt typu std::string
i daje RValue że wyznacza tego celu, 1729
nie ma działań ubocznych i plony wartości 1729 jako rwartość typu int
.
"Lvalues name objects that persist beyond a single expression."
jest w 100% poprawne. Wręcz przeciwnie, twój przykład (const int &)1
jest niepoprawny, ponieważ NIE jest „nazwanym” obiektem.
int &z = 12;
Po prawej stronie tymczasowy obiekt typu int
jest tworzony z integralnego literału 12
, ale tymczasowy nie może być powiązany z odwołaniem innym niż const. Stąd błąd. To jest to samo, co:
int &z = int(12); //still same error
Dlaczego tworzy się tymczasowy? Ponieważ odniesienie musi odnosić się do obiektu w pamięci, a aby obiekt istniał, musi zostać najpierw utworzony. Ponieważ obiekt nie ma nazwy, jest to obiekt tymczasowy . Nie ma imienia. Z tego wyjaśnienia stało się dość jasne, dlaczego drugi przypadek jest w porządku.
Obiekt tymczasowy można powiązać z odniesieniem do const, co oznacza, że możesz to zrobić:
const int &z = 12; //ok
Ze względu na kompletność chciałbym dodać, że C ++ 11 wprowadził rvalue-reference, które można powiązać z tymczasowym obiektem. Więc w C ++ 11 możesz napisać to:
int && z = 12; //C+11 only
Zauważ, że jest &&
intead of &
. Zauważ również, że const
nie jest już potrzebne, mimo że obiekt, z którym się z
łączy, jest tymczasowym obiektem utworzonym z całki-literału 12
.
Ponieważ C ++ 11 wprowadził odwołanie do wartości r , int&
odtąd nazywane jest odniesieniem do wartości .
12
jest stałą czasu kompilacji, której nie można zmienić w przeciwieństwie do danych, do których się odwołuje int&
. Możesz to zrobić
const int& z = 12;
void f( vector<int> const & )
, która jest idiomatyczna, aby przekazać wektor, który nie ma być modyfikowany. Problem polega teraz na tym f( vector<int>(5) )
, że byłoby to niepoprawne, a użytkownik musiałby podać inne przeciążenie, void f( vector<int> v ) { f(v); }
które jest trywialne.
f( vector<int>(5) )
kompilator utworzy tymczasową, a następnie wiąże odwołanie z tym tymczasowym i podobnie jeśli wystąpiła niejawna konwersja z 5
bezpośrednio. Pozwala to kompilatorowi na wygenerowanie pojedynczego podpisu dla funkcji i umożliwia implementację funkcji przez jednego użytkownika. Od tego momentu podobne zachowanie jest definiowane dla pozostałych zastosowań stałych odniesień dla spójności.
T const & r = *ptr;
każde późniejsze użycie r
w funkcji może zostać zastąpione przez *ptr
i r
nie musi istnieć w czasie wykonywania) lub może być zaimplementowane poprzez zachowanie adresu obiektu, do którego przypisuje aliasy (rozważ przechowywanie referencji jako członka obiektu) - który jest implementowany jako wskaźnik z autodreferencją.
Oto zasady języka C ++:
12
) jest „wartością r”int &ri = 12;
jest źle sformułowanaMusisz zrozumieć, że to są reguły C ++. Po prostu są.
Łatwo jest wymyślić inny język, na przykład C ++, z nieco innymi zasadami. W C ++ byłoby dozwolone utworzenie referencji niebędącej stałą z wartością r. Nie ma tu nic niespójnego ani niemożliwego.
Ale pozwoliłoby to na pewien ryzykowny kod, w którym programista mógłby nie uzyskać tego, co zamierzał, a projektanci C ++ słusznie postanowili uniknąć tego ryzyka.
Odniesienia to „ukryte wskaźniki” (niezerowe) do rzeczy, które mogą się zmieniać (lvalues). Nie możesz ich zdefiniować jako stałe. Powinna to być rzecz „zmienna”.
EDYTOWAĆ::
Myślę o
int &x = y;
jako prawie odpowiednik
int* __px = &y;
#define x (*__px)
gdzie __px
jest nową nazwą, a #define x
działa tylko wewnątrz bloku zawierającego deklarację x
odniesienia.
const
:)
const