ref std что это
Контейнер ссылок в C++ или зачем нужен std::reference_wrapper
материал взят с сайта artlang
Прежде чем, тронуть std::reference_wrapper давайте рассмотрим несколько задач, некоторые из которых могут показаться странными на первый взгляд.
Задача первая
Ссылки в C++ не могут выступать в качестве типа элементов массива или контейнера STL:
std::vector cont; // Ошибка на этапе компиляции
Конечно можно использовать указатели в качестве элементов контейнера, однако в этом случае оказывается задействован синтаксис указателей. Поэтому, иногда очень хочется организовать контейнер, хранящий ссылки. Как этого можно добиться? Читаем далее.
Задача вторая
Инициализация ссылки происходит при её объявлении. После объявления ссылки её невозможно привязать к другой переменной. Однако можно легко создать похожее по семантике поведение и сделать что-то вроде “повторной инициализации” ссылки.
Задача третья
Решим все эти задачи.
Начнем давать ответы в обратном порядке.
Задача третья — ответ
Это простой шаблон класса, который хранит внутри себя указатель на данные. Получив ссылку в конструкторе, reference_wrapper узнает адрес переменной __indata с помощью функции std::addressof<> :
Шаблонная функция addressof была также реализована в библиотеке boost. А начиная с нового стандарта C++11 addressof “переместился” в стандартную библиотеку.
Задача вторая — ответ
Задача первая — ответ
Используя такие “контейнеры ссылок”, Вы всегда должны гарантировать, что элементы, на которые Вы ссылаетесь, существуют. Если в этом примере контейнер std::list вдруг внезапно будет уничтожен, пользоваться “контейнером ссылок” (std::vector) будет уже нельзя.
Преимущество этого кода заключается в том, что не используется синтаксис указателей. Даже вызова get() удалось избежать.
В заключение хотелось бы сказать: reference_wrapper возможно не очень популярная “штука” из STL, но Вы врядли сможете избежать её использования в своих программах. Хотя бы косвенно — через вызовы std::ref и std::cref — но Вы задействуете эту простую обертку вокруг обычных указателей.
Русские Блоги
std :: ref функция
Функция std :: ref в C ++ 11 предназначена для решения проблемы копирования значений в процессе создания потока. Далее будет использоваться создание потока для демонстрации роли функции ref.
Сначала напишем создание потока, который принимает в качестве параметра объект класса. Давайте посмотрим на следующий код:
Просто реализуйте класс и выведите адрес в памяти его конструктора, конструктора копирования, деструктора и идентификатора потока. Затем для функции fun создается поток. Параметр является ссылкой на объект A. Теоретически b в функции должен быть псевдонимом для a в основной функции, но фактический результат выполнения показывает, что объект a копируется в процессе создания потока. Копия, поэтому эта передача становится передачей значения, результат операции показан на следующем рисунке:
Поскольку адрес в памяти объекта в функции fun отличается от адреса объекта в основной функции, если мы хотим изменить значение этого объекта в функции fun, он не будет работать в основной функции, что приведет к потере ссылки. Роль.
Если мы изменим значение объекта b в функции fun, потому что параметр, который мы передали, является константой, мы можем использовать ключевое слово mutable для достижения эффекта создания этой переменной-члена данных, так что мы находимся в этих данных Добавьте ключевое слово mutable перед членом, затем измените его в функции fun, а затем выведите значение объекта в функции fun и основной функции. Код и результаты выполнения следующие:
Если мы хотим реализовать функцию реальной ссылки, нам нужно использовать функцию std :: ref. Код выглядит следующим образом:
Результаты операции следующие:
Можно видеть, что конструктор копирования не вызывается в процессе передачи параметров, а адрес памяти тот же, и измененное значение достигло желаемого эффекта, но для обеспечения безопасности потока этот метод не может использовать отсоединение, чтобы сделать основной поток и дочерний Нити разделены.
ссылка — C ++ Разница между std :: ref (T) и T & amp;?
У меня есть несколько вопросов относительно этой программы:
Я хочу знать, если std::ref не возвращает ссылку на объект, тогда что он делает? По сути, в чем разница между:
Кроме того, я хочу знать, почему существует эта разница? Зачем нам std::ref или же std::reference_wrapper когда у нас есть ссылки (т.е. T& )?
Решение
Что ж ref конструирует объект соответствующего reference_wrapper тип для хранения ссылки на объект. Что означает, когда вы подаете заявление:
reference_wrapper очень полезно, когда вы хотите подражать reference объекта, который может быть скопирован (это как copy-constructible а также copy-assignable ).
Однако это законно:
Позвольте мне показать вам программу: —
Смотрите здесь, мы узнаем три вещи:
r на самом деле действует как настоящий reference ( Смотри как r.get()=70 изменил значение y ).
Я надеюсь, что этого ответа более чем достаточно, чтобы объяснить ваши сомнения.
Другие решения
std::reference_wrapper признается стандартными средствами, чтобы иметь возможность передавать объекты по ссылке в контексте передачи по значению.
Например, std::bind может взять в std::ref() передайте его по значению и позже распакуйте обратно в ссылку.
Этот фрагмент выводит:
Ссылка ( T& или же T&& ) является специальным элементом в языке C ++. Это позволяет манипулировать объектом по ссылке и имеет особые случаи использования на языке. Например, вы не можете создать стандартный контейнер для хранения ссылок: vector плохо сформирован и генерирует ошибку компиляции.
std::reference_wrapper с другой стороны, это объект C ++, способный содержать ссылку. Таким образом, вы можете использовать его в стандартных контейнерах.
std::ref это стандартная функция, которая возвращает std::reference_wrapper на его аргумент. В той же идее std::cref возвращается std::reference_wrapper к постоянной ссылке.
std::ref and std::reference_ wrapper: common use cases
reference_wrapper provides reference semantics along with the resilience to rebind to a different object.
1. Short Intro
std::reference_wrapper is a copyable and assignable object that imitates a reference (T&). It gives the non-nullable guarantee of a reference and the pointer-like flexibility to rebind to another object.
The usual way to create an std::reference_wrapper is via std::ref (or std::cref for reference_wrapper ). A contrived example:
Read on for details.
2. Motivation
However, a reference is a stubborn alias of an object. That presents some challenges, like the one shown above where the function template parameter type has to be explicitly specified to pass by reference.
Also, we cannot get the address of a reference itself because a reference is not an object (a region of storage) according to the C++ standard. Declaring a reference to a reference, an array of references, and a pointer to a reference is forbidden in C++. Because of that, reference types do not meet the Erasable requirement of STL container elements. Therefore, we cannot have a container (e.g., vector or list) of reference elements:
Moreover, a reference cannot rebind to another object. Therefore, assigning a reference to another does not assign the reference itself; it assigns the object:
As references cannot rebind, having a reference class member is a pain in the neck because a reference member makes a class non-assignable — the default copy-assignment operator is deleted. Move-semantics does not make sense with a reference member altogether.
An std::reference_wrapper is a copyable and assignable object that emulates a reference. Contrary to its name, it does not wrap a reference. It works by encapsulating a pointer (T*) and by implicitly converting to a reference (T&). It cannot be default constructed or initialized with a temporary; therefore, it cannot be null or invalid:
The only downside is that to access the members of an object (T), we have to use the ‘std::reference_wrapper ::get‘ method:
Also, to assign to the referred object use ‘get()‘:
Hopefully, using ‘get()‘ would not be necessary when C++ supports overloading operator dot(.) and the concept of smart-references someday. See proposal N4477.
We can have a vector of std::reference_wrapper, have it as a member of a class, and more as we see in the next section.
3. Common Use Cases
3.1. With make_pair and make_tuple
std::reference_wrapper can be used as an argument to a template function (or constructor) to avoid specifying the template parameter types explicitly. A peculiar case here is of make_pair (make_tuple) whose purpose is to cut the verbosity associated with instantiating a pair (tuple). Compare these:
Another advantage of reference_wrapper is that it cannot be instantiated with a temporary. E.g., the following is an undefined-behavior (UB) because the temporary’s life is extended only until the constructor parameter goes out of scope:
The above case is of dangling reference, which can be avoided with reference_wrapper:
The make_pair and make_tuple are somewhat irrelevant since the C++17’s class template argument deduction (CTAD). But the reasons still apply, now, with the constructors:
However, there is a subtlety associated with make_pair and make_tuple, which should not be so important in most cases. The make_pair and make_tuple decay a reference_wrapper to a reference (T&), whereas, that is not the case with CTAD construction of pair and tuple.
3.2. Container of references
Unlike a reference, a reference_wrapper is an object and thus satisfies the STL container element requirements (Erasable, to be precise). Therefore, reference_wrapper can be used as a vector element type.
A reference_wrapper could be a safe alternative to a pointer type (T*) for storing in a vector:
3.3. Passing args by reference to start-function via std::thread
We can pass arguments to the start-function when creating a new thread via std::thread(startFunction, args). Those arguments are passed by value from the thread creator function because the std::thread constructor copies or moves the creator’s arguments before passing them to the start-function.
So, a start-function’s reference parameter cannot bind to a creator’s argument. It can only bind to a temporary created by std::thread:
If we want to pass an argument to a start-function by reference, we do that through std::ref, as follows:
3.4. Reference as a class member
Having a reference class member poses problems, such that, it makes the class non-assignable and practically immovable:
The usual practice is to avoid references as class members and use pointers instead.
A reference_wrapper offers the best of both worlds:
3.5. Passing a function object by reference
An std::reference_wrapper can be invoked like a function as long as the T is a callable. This feature is particularly useful with STL algorithms if we want to avoid copying a large or stateful function object.
Besides, T can be any callable – a regular function, a lambda, or a function object. For example:
3.6. With bind expressions
std::bind generates a callable wrapper known as bind expression that forwards the call to a wrapped-callable. A bind expression can have some or all of the wrapped-callable’s parameters bound.
However, the bound arguments are copied or moved in a bind expression.
Therefore, we need to use std::ref (or std::cref) if we want to pass the bound parameters by reference:
std:: reference_wrapper
Compiler support | ||||
Freestanding and hosted | ||||
Language | ||||
Standard library headers | ||||
Named requirements | ||||
Feature test macros (C++20) | ||||
Language support library | ||||
Concepts library (C++20) | ||||
Diagnostics library | ||||
General utilities library | ||||
Strings library | ||||
Containers library | ||||
Iterators library | ||||
Ranges library (C++20) | ||||
Algorithms library | ||||
Numerics library | ||||
Localizations library | ||||
Input/output library | ||||
Filesystem library (C++17) | ||||
Regular expressions library (C++11) | ||||
Atomic operations library (C++11) | ||||
Thread support library (C++11) | ||||
Technical specifications | ||||
Symbols index | ||||
External libraries |
Language support | ||||
Type support (basic types, RTTI, type traits) | ||||
Library feature-test macros (C++20) | ||||
Dynamic memory management | ||||
Program utilities | ||||
Error handling | ||||
Coroutine support (C++20) | ||||
Variadic functions | ||||