这是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_wrapperoperator =和一个非显式的构造函数,请参阅文档 。

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

f2将本地reference_wrapper重新绑定到xx

arg = xx;

本地arg现在指的是(读作为绑定) xx 。 (而不再指j

arg += xx;

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

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