Это поведение 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.

Что мне не хватает?

66

Решение

Небольшая модификация f2 предоставляет ключ:

template<class T>
void f2(T arg)
{
arg.get() = xx;
}

Это теперь делает то, что вы ожидаете.

Это произошло потому, что std::ref возвращает std::reference_wrapper<> объект. Оператор присваивания которого повторное связывание обертка.
(увидеть http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D)

Он не присваивает завернутую ссылку.

в f1 случай, все работает так, как вы ожидали, потому что std::reference_wrapper<T> предоставляет оператор преобразования в T&, который будет привязан к неявной правой части intс неявным operator+,

56

Другие решения

reference_wrapper имеет operator = и неявный конструктор, см. документация.

Итак, даже если это удивительно, это нормальное поведение:

f2 связывает локальный reference_wrapper с xx,

11

arg = xx;

Местный arg теперь относится к (читается как связывает с) xx, (И больше не относится к j)

arg += xx;

неявный operator T& () применяется в соответствии с аргументом operator += и, следовательно, добавление выполняется для упомянутого объекта, т.е. j,

Таким образом, наблюдаемое поведение является правильным.

8
По вопросам рекламы [email protected]