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

Is this std::ref behaviour logical?

本文关键字:合乎逻辑 std ref 这是      更新时间:2023-10-16

请考虑以下代码:

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

我错过了什么?

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+的隐式右侧。

reference_wrapper具有operator =和非显式构造函数,请参阅文档。

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

f2将本地reference_wrapper重新绑定到xx

arg = xx;

本地arg现在引用(读作绑定(xx。(不再提及j(

arg += xx;

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

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