Это поведение std::ref логично?
рассмотрим этот код:
#include <iostream>
#include <functional>
int xx = 7;
template<class T>
void f1(T arg)
{
arg += xx;
}
template<class T>
void f2(T arg)
{
arg = xx;
}
int main()
{
int j;
j=100;
f1(std::ref(j));
std::cout << j << std::endl;
j=100;
f2(std::ref(j));
std::cout << j << std::endl;
}
при выполнении этот код выводит
107
100
Я ожидал бы, что второе значение будет 7, а не 100.
чего мне не хватает?
3 ответа:
небольшая модификация
f2
предоставляет подсказку:template<class T> void f2(T arg) { arg.get() = xx; }
это сейчас делает то, что вы ожидаете.
это произошло потому, что
std::ref
возвращает astd::reference_wrapper<>
"объект". Оператор присваивания которого привязывает фантик. (см. http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D)он не присваивает обернутую ссылку.
на
f1
случае, все работает, как вы ожидали, потому чтоstd::reference_wrapper<T>
предоставляет оператор преобразования кT&
, который будет привязан к неявной правой частиint
s implicitoperator+
.
reference_wrapper
иoperator =
и не явный конструктор, см. документация.так, даже если это удивительно, это нормальное поведение:
f2
привязывает к местной reference_wrapperxx
.
arg = xx;
Local
arg
теперь относится к (читается как связывается с)xx
. (И больше не относится кj
)
arg += xx;
подразумевается
operator T& ()
применяется для соответствия аргументуoperator +=
и, следовательно, добавление выполняется на указанный объект т. е.j
.таким образом, наблюдаемое поведение является правильным.