考虑以下代码:
#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。
我错过了什么?
答案 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_wrapper
有operator =
和非显式构造函数,请参阅documentation。
所以,即使这是令人惊讶的,这也是正常行为:
f2
将本地reference_wrap重新绑定到xx
。
答案 2 :(得分:9)
arg = xx;
本地arg
现在指的是(与其绑定)xx
。 (并且不再提及j
)
arg += xx;
应用隐式operator T& ()
来匹配operator +=
的参数,因此对引用的对象即j
执行添加。
所以观察到的行为是正确的。