std::reference_wrapperкорисна в поєднанні з шаблонами. Він обгортає об’єкт, зберігаючи вказівник на нього, дозволяючи перепризначити та копіювати, наслідуючи його звичайну семантику. Він також інструктує певні шаблони бібліотеки зберігати посилання замість об'єктів.
Розглянемо алгоритми в STL, які копіюють функтори: Ви можете уникнути цієї копії, просто передавши обгортку посилання, що стосується функтора, а не самого функтора.
unsigned arr[10];
std::mt19937 myEngine;
std::generate_n( arr, 10, std::ref(myEngine) ); // Modifies myEngine's state
Це працює, тому що ...
... reference_wrapperсек перевантаженняoperator() так їх можна назвати так само , як функції об'єктів вони ставляться до:
std::ref(myEngine)() // Valid expression, modifies myEngines state
… (Un) як звичайні посилання, копіювання (і призначення) reference_wrappersпросто призначає пуанте.
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>
Копіювання обгортки посилання практично еквівалентно копіюванню покажчика, що коштує так само дешево. Усі виклики функції, притаманні її використанню (наприклад, ті, що потрібно operator()), повинні бути просто вписані, оскільки вони є однолінійними.
reference_wrappers створюються з допомогою std::refіstd::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>
Аргумент шаблону визначає тип та cv-кваліфікацію об'єкта, про який йдеться; r2посилається на a const intі дасть лише посилання на const int. Виклики на посилання на обгортки з constфункторами будуть викликати лише constфункцію члена operator()s.
Ініціалізатори Rvalue заборонені, оскільки дозволити їм принести більше шкоди, ніж користі. Оскільки rvalues було б переміщено в будь-якому випадку (і з гарантованою елісією копії навіть цього частково уникнути), ми не вдосконалюємо семантику; ми можемо запровадити звисаючі покажчики, однак, оскільки опорна оболонка не продовжує термін служби пуанте.
Бібліотечна взаємодія
Як було сказано раніше, можна доручити make_tupleзберігати посилання в отриманому tuple, передаючи відповідний аргумент через 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&>
Зауважимо, що це трохи відрізняється від forward_as_tuple: Тут, rvalues, оскільки аргументи не дозволені.
std::bindпоказує таку ж поведінку: він не копіює аргумент, а зберігає посилання, якщо він є reference_wrapper. Корисно, якщо цей аргумент (або функтор!) Не потрібно копіювати, а залишається в області застосування, коли використовується bind-functor.
Відмінність від звичайних покажчиків
Немає додаткового рівня синтаксичної непрямості. Покажчики повинні бути зменшені, щоб отримати значення на об'єкт, на який вони посилаються; reference_wrappers мають неявний оператор перетворення, і його можна викликати як об'єкт, який вони обертають.
int i;
int& ref = std::ref(i); // Okay
reference_wrappers, на відміну від покажчиків, не мають нульового стану. Вони повинні бути ініціалізовані або посиланням, або іншимreference_wrapper .
std::reference_wrapper<int> r; // Invalid
Подібною є семантика дрібної копії: Покажчики та reference_wrappers можуть бути перепризначені.
.замість->