这种 std::ref 行为合乎逻辑吗?
Is this std::ref behaviour logical?
考虑这段代码:
#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
returns 一个 std::reference_wrapper<>
对象。 重新绑定 包装器的赋值运算符。
(参见 http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D)
它不对包装引用进行赋值。
在 f1
的情况下,一切都按您预期的那样工作,因为 std::reference_wrapper<T>
提供了一个到 T&
的转换运算符,它将绑定到 [= 的隐式右侧17=]s 隐式 operator+
.
reference_wrapper
有 operator =
和一个非显式构造函数,请参阅 documentation。
所以,即使令人惊讶,这也是正常行为:
f2
将本地 reference_wrapper 重新绑定到 xx
。
arg = xx;
本地 arg
现在指的是(读作绑定)xx
。 (且不再指j
)
arg += xx;
隐式 operator T& ()
用于匹配 operator +=
的参数,因此对引用对象执行加法,即 j
.
所以观察到的行为是正确的。
考虑这段代码:
#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
returns 一个 std::reference_wrapper<>
对象。 重新绑定 包装器的赋值运算符。
(参见 http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D)
它不对包装引用进行赋值。
在 f1
的情况下,一切都按您预期的那样工作,因为 std::reference_wrapper<T>
提供了一个到 T&
的转换运算符,它将绑定到 [= 的隐式右侧17=]s 隐式 operator+
.
reference_wrapper
有 operator =
和一个非显式构造函数,请参阅 documentation。
所以,即使令人惊讶,这也是正常行为:
f2
将本地 reference_wrapper 重新绑定到 xx
。
arg = xx;
本地 arg
现在指的是(读作绑定)xx
。 (且不再指j
)
arg += xx;
隐式 operator T& ()
用于匹配 operator +=
的参数,因此对引用对象执行加法,即 j
.
所以观察到的行为是正确的。