Bentuk yang salah:
int &z = 12;
Bentuk yang benar:
int y;
int &r = y;
Pertanyaan :
Mengapa kode pertama salah? Apa " arti " dari kesalahan dalam judul?
Bentuk yang salah:
int &z = 12;
Bentuk yang benar:
int y;
int &r = y;
Pertanyaan :
Mengapa kode pertama salah? Apa " arti " dari kesalahan dalam judul?
(ostringstream() << "x=" << x).str()
Jawaban:
C ++ 03 3.10 / 1 mengatakan: "Setiap ekspresi adalah nilai l atau nilai r." Penting untuk diingat bahwa lvalueness versus rvalueness adalah properti ekspresi, bukan objek.
Lvalues nama objek yang tetap ada di luar ekspresi tunggal. Sebagai contoh, obj
, *ptr
, ptr[index]
, dan ++x
semua lvalues.
Nilai R adalah nilai temporer yang menguap pada akhir ekspresi penuh tempat nilai tersebut berada ("di titik koma"). Sebagai contoh, 1729
, x + y
, std::string("meow")
, dan x++
semua rvalues.
Operator alamat mensyaratkan bahwa "operan harus menjadi nilai l". jika kita bisa mengambil alamat dari satu ekspresi, ekspresi itu adalah nilai l, jika tidak, itu adalah nilai r.
&obj; // valid
&12; //invalid
int & = 12;
tidak valid, standar mengatakan string literal adalah nilai l, literal lainnya adalah nilai r.
std::string("meow")
membuat objek berjenis std::string
dan menghasilkan nilai r yang menunjukkan objek ini, 1729
tidak memiliki efek samping dan menghasilkan nilai 1729 sebagai nilai r dari tipe int
.
"Lvalues name objects that persist beyond a single expression."
adalah pernyataan yang 100% benar. Sebaliknya, contoh Anda (const int &)1
salah, karena Ini BUKAN objek "bernama".
int &z = 12;
Di sisi kanan, objek sementara tipe int
dibuat dari literal integral 12
, tetapi sementara tidak dapat terikat ke referensi non-const. Karena itu kesalahannya. Itu sama dengan:
int &z = int(12); //still same error
Mengapa sementara dibuat? Karena referensi harus merujuk ke objek dalam memori, dan agar objek ada, itu harus dibuat terlebih dahulu. Karena objek tidak bernama, itu adalah objek sementara . Tidak ada nama. Dari penjelasan ini, menjadi sangat jelas mengapa kasus kedua baik-baik saja.
Objek sementara dapat diikat ke referensi const, yang berarti, Anda dapat melakukan ini:
const int &z = 12; //ok
Demi kelengkapan, saya ingin menambahkan bahwa C ++ 11 telah memperkenalkan rvalue-reference, yang dapat mengikat objek sementara. Jadi di C ++ 11, Anda bisa menulis ini:
int && z = 12; //C+11 only
Perhatikan bahwa ada &&
pengganti &
. Perhatikan juga bahwa const
sudah tidak dibutuhkan lagi, padahal objek yang z
diikat merupakan objek sementara yang dibuat dari integral-literal 12
.
Karena C ++ 11 telah memperkenalkan rvalue-reference , untuk int&
selanjutnya disebut lvalue-reference .
12
adalah konstanta waktu kompilasi yang tidak dapat diubah tidak seperti data yang dirujuk int&
. Yang bisa Anda lakukan adalah
const int& z = 12;
void f( vector<int> const & )
, yang idiomatis melewatkan vektor yang tidak akan dimodifikasi. Masalahnya sekarang adalah itu f( vector<int>(5) )
tidak benar, dan pengguna harus memberikan kelebihan beban berbeda void f( vector<int> v ) { f(v); }
yang sepele.
f( vector<int>(5) )
, kompilator membuat sementara dan kemudian mengikat referensi ke sementara itu, dan serupa jika ada konversi implisit dari 5
langsung. Hal ini memungkinkan kompiler untuk menghasilkan satu tanda tangan untuk fungsi tersebut dan memungkinkan implementasi fungsi oleh pengguna tunggal. Sejak saat itu, perilaku serupa didefinisikan untuk sisa penggunaan referensi konstan untuk konsistensi.
T const & r = *ptr;
, penggunaan nanti r
dalam fungsi dapat diganti *ptr
, dan r
tidak perlu ada saat runtime) atau mungkin harus diimplementasikan dengan menyimpan alamat objek yang alias (pertimbangkan untuk menyimpan referensi sebagai anggota objek) - yang diimplementasikan sebagai penunjuk autodereferensi.
Ini adalah aturan bahasa C ++:
12
) adalah "nilai r"int &ri = 12;
berbentuk burukAnda harus memahami bahwa ini adalah aturan C ++. Mereka memang begitu.
Sangat mudah untuk menemukan bahasa yang berbeda, katakanlah C ++ ', dengan aturan yang sedikit berbeda. Dalam C ++ ', akan diizinkan untuk membuat referensi non-const dengan rvalue. Tidak ada yang tidak konsisten atau tidak mungkin di sini.
Tetapi itu akan memungkinkan beberapa kode berisiko di mana pemrogram mungkin tidak mendapatkan apa yang dia inginkan, dan perancang C ++ dengan tepat memutuskan untuk menghindari risiko itu.
Referensi adalah "petunjuk tersembunyi" (bukan nol) ke hal-hal yang dapat berubah (lvalues). Anda tidak dapat mendefinisikannya menjadi sebuah konstanta. Ini harus menjadi hal "variabel".
EDIT ::
Saya sedang memikirkan
int &x = y;
hampir setara dengan
int* __px = &y;
#define x (*__px)
where __px
is a fresh name, and the #define x
works only inside the block of the declaration of x
reference.
const
:)
const