PENGANTAR
ISOC ++ 11 (secara resmi ISO / IEC 14882: 2011) adalah versi terbaru dari standar bahasa pemrograman C ++. Ini berisi beberapa fitur baru, dan konsep, misalnya:
- referensi nilai
- xvalue, glvalue, prvalue kategori nilai ekspresi
- pindahkan semantik
Jika kami ingin memahami konsep kategori nilai ekspresi baru, kami harus mengetahui bahwa ada referensi nilai dan nilai. Lebih baik untuk mengetahui nilai dapat diteruskan ke referensi nilai non-const.
int& r_i=7; // compile error
int&& rr_i=7; // OK
Kita dapat memperoleh beberapa intuisi dari konsep kategori nilai jika kita mengutip sub-bagian berjudul Lvalues dan rvalues dari draft kerja N3337 (draft paling mirip dengan standar ISOC ++ 11 yang diterbitkan).
3.10 Nilai dan nilai [basic.lval]
1 Ekspresi dikategorikan menurut taksonomi pada Gambar 1.
- Nilai l (disebut demikian, secara historis, karena nilai bisa muncul di sebelah kiri ekspresi penugasan) menunjuk fungsi atau objek. [Contoh: Jika E adalah ekspresi dari tipe pointer, maka * E adalah ekspresi lvalue yang merujuk pada objek atau fungsi yang ditunjuk oleh E. Sebagai contoh lain, hasil memanggil fungsi yang tipe kembaliannya adalah referensi lvalue adalah lvalue. —Kirim contoh]
- Nilai x (nilai "eXpiring") juga merujuk ke objek, biasanya mendekati akhir masa pakainya (sehingga sumber dayanya dapat dipindahkan, misalnya). Nilai x adalah hasil dari jenis ekspresi tertentu yang melibatkan referensi nilai (8.3.2). [Contoh: Hasil memanggil fungsi yang tipe kembaliannya merupakan referensi nilai adalah nilai x. —Kirim contoh]
- Glvalue (lvalue "umum") adalah lvalue atau xvalue.
- Nilai sebuah (disebut, secara historis, karena nilai bisa muncul di sisi kanan ekspresi penugasan) adalah nilai x,
objek sementara (12.2) atau sub-objek daripadanya, atau nilai yang tidak
terkait dengan objek.
- Prvalue (“pure” rvalue) adalah rvalue yang bukan xvalue. [Contoh: Hasil memanggil fungsi yang tipe kembaliannya bukan
referensi adalah nilai awal. Nilai literal seperti 12, 7.3e5, atau
true juga merupakan nilai awal. —Kirim contoh]
Setiap ungkapan termasuk salah satu klasifikasi mendasar dalam taksonomi ini: nilai, nilai, atau nilai. Properti ekspresi ini disebut kategori nilainya.
Tetapi saya tidak begitu yakin tentang ayat ini cukup untuk memahami konsep-konsep dengan jelas, karena "biasanya" tidak benar-benar umum, "mendekati akhir masa hidupnya" tidak benar-benar konkret, "melibatkan referensi nilai" tidak benar-benar jelas, dan "Contoh: Hasil memanggil fungsi yang tipe kembaliannya merupakan referensi nilai adalah nilai x." terdengar seperti ular menggigit ekornya.
KATEGORI NILAI PRIMER
Setiap ekspresi memiliki tepat satu kategori nilai primer. Kategori-kategori nilai ini adalah kategori nilai, nilai, dan kategori nilai awal.
nilai-nilai
Ekspresi E milik kategori nilai jika dan hanya jika E merujuk ke entitas yang SUDAH memiliki identitas (alamat, nama atau alias) yang membuatnya dapat diakses di luar E.
#include <iostream>
int i=7;
const int& f(){
return i;
}
int main()
{
std::cout<<&"www"<<std::endl; // The expression "www" in this row is an lvalue expression, because string literals are arrays and every array has an address.
i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
i; // ... as the entity the expression i in this row refers to.
int* p_i=new int(7);
*p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
*p_i; // ... as the entity the expression *p_i in this row refers to.
const int& r_I=7;
r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
r_I; // ... as the entity the expression r_I in this row refers to.
f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
i; // ... as the entity the expression f() in this row refers to.
return 0;
}
nilai x
Ekspresi E milik kategori xvalue jika dan hanya jika itu
- hasil memanggil suatu fungsi, baik secara implisit atau eksplisit, yang tipe pengembaliannya merupakan rvalue referensi ke tipe objek yang dikembalikan, atau
int&& f(){
return 3;
}
int main()
{
f(); // The expression f() belongs to the xvalue category, because f() return type is an rvalue reference to object type.
return 0;
}
- pemeran untuk referensi nilai ke tipe objek, atau
int main()
{
static_cast<int&&>(7); // The expression static_cast<int&&>(7) belongs to the xvalue category, because it is a cast to an rvalue reference to object type.
std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).
return 0;
}
- ekspresi akses anggota kelas yang menunjuk anggota data non-statis dari tipe non-referensi di mana ekspresi objek adalah xvalue, atau
struct As
{
int i;
};
As&& f(){
return As();
}
int main()
{
f().i; // The expression f().i belongs to the xvalue category, because As::i is a non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.
return 0;
}
- ekspresi pointer-ke-anggota di mana operan pertama adalah nilai x dan operan kedua adalah pointer ke anggota data.
Perhatikan bahwa efek dari aturan di atas adalah bahwa rujukan nilai yang dinamai objek diperlakukan sebagai lvalues dan referensi rvalue yang tidak disebutkan namanya untuk objek diperlakukan sebagai nilai x; referensi nilai untuk fungsi diperlakukan sebagai nilai apakah namanya atau tidak.
#include <functional>
struct As
{
int i;
};
As&& f(){
return As();
}
int main()
{
f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
As&& rr_a=As();
rr_a; // The expression rr_a belongs to the lvalue category, because it refers to a named rvalue reference to object.
std::ref(f); // The expression std::ref(f) belongs to the lvalue category, because it refers to an rvalue reference to function.
return 0;
}
nilai-nilai
Ekspresi E termasuk dalam kategori nilai awal jika dan hanya jika E tidak termasuk dalam kategori nilai rendah atau juga untuk kategori harga rendah.
struct As
{
void f(){
this; // The expression this is a prvalue expression. Note, that the expression this is not a variable.
}
};
As f(){
return As();
}
int main()
{
f(); // The expression f() belongs to the prvalue category, because it belongs neither to the lvalue nor to the xvalue category.
return 0;
}
KATEGORI NILAI CAMPURAN
Ada dua kategori nilai campuran lebih lanjut yang penting. Kategori nilai ini adalah kategori rvalue dan glvalue.
nilai-nilai
Ekspresi E milik kategori nilai jika dan hanya jika E milik kategori nilai, atau ke kategori nilai awal.
Perhatikan bahwa definisi ini berarti bahwa ekspresi E milik kategori nilai jika dan hanya jika E mengacu pada entitas yang tidak memiliki identitas yang membuatnya dapat diakses di luar E YET.
nilai-nilai
Ekspresi E milik kategori glvalue jika dan hanya jika E milik kategori lvalue, atau ke kategori xvalue.
ATURAN PRAKTIS
Scott Meyer telah menerbitkan aturan praktis yang sangat berguna untuk membedakan nilai-nilai dari nilai-nilai.
- Jika Anda dapat mengambil alamat suatu ekspresi, ekspresi tersebut adalah nilai.
- Jika jenis ekspresi adalah referensi nilai (misalnya, T & atau const T &, dll.), Ekspresi itu adalah nilai.
- Kalau tidak, ekspresi adalah nilai. Secara konseptual (dan biasanya juga sebenarnya), nilai-nilai sesuai dengan objek sementara, seperti yang dikembalikan dari fungsi atau dibuat melalui konversi tipe implisit. Sebagian besar nilai literal (misalnya, 10 dan 5.3) juga merupakan nilai.