2016-05-08 73 views
66

考慮以下代碼:這是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

我缺少什麼?

+16

引用包裝是可復位的,所以分配引用的內容,而不是引用的對象。 –

+1

優秀的問題! – vsoftco

回答

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&,其將結合到int內隱operator+隱含的右手邊。

+1

你需要工作嗎? – Ramy

+0

好的,非常感謝 – Ramy

11

reference_wrapperoperator =和一個非顯式構造函數,請參見documentation

所以,即使它是令人驚訝的,這是正常的行爲:

f2重新綁定本地的reference_wrapper到xx

8

arg = xx;

本地arg現指(讀作用結合)xx。 (而沒有更多的指j

arg += xx;

operator T&()被施加到匹配operator +=,因此另外的參數被稱爲對象即j執行。

所以觀察到的行爲是正確的。