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_wrapper
s створюються з допомогою 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_wrapper
s мають неявний оператор перетворення, і його можна викликати як об'єкт, який вони обертають.
int i;
int& ref = std::ref(i); // Okay
reference_wrapper
s, на відміну від покажчиків, не мають нульового стану. Вони повинні бути ініціалізовані або посиланням, або іншимreference_wrapper
.
std::reference_wrapper<int> r; // Invalid
Подібною є семантика дрібної копії: Покажчики та reference_wrapper
s можуть бути перепризначені.
.
замість->