std::reference_wrapper
berguna jika dikombinasikan dengan template. Ini membungkus objek dengan menyimpan penunjuk ke sana, memungkinkan untuk penugasan ulang dan menyalin sambil meniru semantik biasanya. Ini juga menginstruksikan templat perpustakaan tertentu untuk menyimpan referensi, bukan objek.
Pertimbangkan algoritme di STL yang menyalin functor: Anda dapat menghindari penyalinan itu hanya dengan meneruskan pembungkus referensi yang merujuk ke functor alih-alih functor itu sendiri:
unsigned arr[10];
std::mt19937 myEngine;
std::generate_n( arr, 10, std::ref(myEngine) ); // Modifies myEngine's state
Ini berfungsi karena…
… reference_wrapper
S overloadoperator()
sehingga mereka dapat dipanggil seperti objek fungsi yang dirujuknya:
std::ref(myEngine)() // Valid expression, modifies myEngines state
… (Tidak) seperti referensi biasa, menyalin (dan menetapkan) reference_wrappers
hanya menugaskan orang yang ditunjuk.
int i, j;
auto r = std::ref(i); // r refers to i
r = std::ref(j); // Okay; r refers to j
r = std::cref(j); // Error: Cannot bind reference_wrapper<int> to <const int>
Menyalin pembungkus referensi secara praktis sama dengan menyalin penunjuk, yang semurah harganya. Semua pemanggilan fungsi yang melekat dalam penggunaannya (misalnya yang ke operator()
) harus hanya sebaris karena merupakan satu baris.
reference_wrapper
s dibuat melalui std::ref
danstd::cref
:
int i;
auto r = std::ref(i); // r is of type std::reference_wrapper<int>
auto r2 = std::cref(i); // r is of type std::reference_wrapper<const int>
Argumen template menentukan tipe dan kualifikasi cv dari objek yang dirujuk; r2
mengacu pada a const int
dan hanya akan menghasilkan referensi ke const int
. Panggilan ke pembungkus referensi dengan fungsi const
di dalamnya hanya akan memanggil const
fungsi anggota operator()
.
Rvalue penginisialisasi tidak diizinkan, karena mengizinkannya akan lebih merugikan daripada menguntungkan. Karena rvalues akan dipindahkan bagaimanapun juga (dan dengan penghapusan salinan yang dijamin bahkan itu dihindari sebagian), kami tidak meningkatkan semantik; kami dapat memperkenalkan petunjuk yang menjuntai, karena pembungkus referensi tidak memperpanjang umur penerima.
Interaksi perpustakaan
Seperti disebutkan sebelumnya, seseorang dapat menginstruksikan make_tuple
untuk menyimpan referensi dalam hasil tuple
dengan meneruskan argumen terkait melalui reference_wrapper
:
int i;
auto t1 = std::make_tuple(i); // Copies i. Type of t1 is tuple<int>
auto t2 = std::make_tuple(std::ref(i)); // Saves a reference to i.
// Type of t2 is tuple<int&>
Perhatikan bahwa ini sedikit berbeda dari forward_as_tuple
: Di sini, nilai r sebagai argumen tidak diperbolehkan.
std::bind
menunjukkan perilaku yang sama: Ini tidak akan menyalin argumen tetapi menyimpan referensi jika itu adalah reference_wrapper
. Berguna jika argumen itu (atau functor!) Tidak perlu disalin tetapi tetap dalam ruang lingkup sementara bind
-functor digunakan.
Perbedaan dari petunjuk biasa
Tidak ada tingkat tambahan dari tipuan sintaksis. Pointer harus direferensikan untuk mendapatkan nilai l ke objek yang dirujuk; reference_wrapper
s memiliki operator konversi implisit dan dapat dipanggil seperti objek yang dibungkusnya.
int i;
int& ref = std::ref(i); // Okay
reference_wrapper
s, tidak seperti pointer, tidak memiliki status null. Mereka harus diinisialisasi dengan referensi atau lainnyareference_wrapper
.
std::reference_wrapper<int> r; // Invalid
Kesamaannya adalah semantik salinan yang dangkal: Pointer dan reference_wrapper
s dapat ditetapkan ulang.
.
dengan alih-alih->