这是std :: ref行为逻辑?
考虑这个代码:
#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上执行加法operator += 。
所以观察到的行为是正确的。