这是std :: ref行为逻辑上的吗?


68

考虑以下代码:

#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。

我想念什么?


17
参考包装器是可重定位的,因此可以分配更改引用的内容,而不是引用的对象。
Kerrek SB

Answers:


57

进行一些小的修改以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情况下,所有操作都按预期工作,因为astd::reference_wrapper<T>提供了的转换操作符T&,它将绑定到ints的隐式右侧operator+


1
你需要工作吗?
拉米

12

reference_wrapper具有operator =和非显式构造函数,请参见documentation

因此,即使令人惊讶,这也是正常的行为:

f2将本地reference_wrapper重新绑定到xx


10

arg = xx;

arg现在,本地是指(读为与绑定)xx。(不再参考j

arg += xx;

隐式operator T& ()应用于匹配的自变量,operator +=因此对所引用的对象(即)执行加法j

因此,观察到的行为是正确的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.