【问题标题】:Is this std::ref behaviour logical?这 std::ref 行为合乎逻辑吗?
【发布时间】:2016-09-03 05:37:23
【问题描述】:

考虑这段代码:

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

我错过了什么?

【问题讨论】:

  • 引用包装器是可重新安装的,因此分配会更改引用的内容,而不是引用的对象。

标签: c++ c++11 ref


【解决方案1】:

f2 的小修改提供了线索:

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

这现在符合您的预期。

这是因为std::ref 返回了一个std::reference_wrapper&lt;&gt; 对象。 重新绑定包装器的赋值运算符。 (见http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D

它不会对包装的引用进行赋值。

f1 的情况下,一切都如您所愿,因为std::reference_wrapper&lt;T&gt;T&amp; 提供了一个转换运算符,它将绑定到ints 隐式operator+ 的隐式右侧。

【讨论】:

  • 你需要一份工作吗?
【解决方案2】:

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

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

f2 将本地 reference_wrapper 重新绑定到 xx

【讨论】:

    【解决方案3】:

    arg = xx;

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

    arg += xx;

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多