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

oz1*_*1cz 68 c++ ref c++11

考虑以下代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

执行时,此代码输出

107
100
Run Code Online (Sandbox Code Playgroud)

我原以为第二个值是7而不是100.

我错过了什么?

Ric*_*ges 57

一个小修改f2提供线索:

template<class T>
void f2(T arg)
{
    arg.get() = xx;
}
Run Code Online (Sandbox Code Playgroud)

这现在符合您的期望.

发生这种情况是因为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+.


Jar*_*d42 12

reference_wrapperhas operator =和非显式构造函数,请参阅文档.

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

f2将本地reference_wrap重新绑定到xx.


Moh*_*ain 10

arg = xx;

本地arg现在指(读作绑定)xx.(并没有更多指j)

arg += xx;

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

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