这个std :: ref行为是否合乎逻辑?

时间:2016-05-08 15:08:04

标签: c++ c++11 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 个答案:

答案 0 :(得分:56)

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&提供了转化运算符,该运算符将绑定到{{1}的隐式右侧隐式int

答案 1 :(得分:11)

reference_wrapperoperator =和非显式构造函数,请参阅documentation

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

f2将本地reference_wrap重新绑定到xx

答案 2 :(得分:9)

  

arg = xx;

本地arg现在指的是(与其绑定)xx。 (并且不再提及j

  

arg += xx;

应用隐式operator T& ()来匹配operator +=的参数,因此对引用的对象即j执行添加。

所以观察到的行为是正确的。