2016-05-08 8 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 

私は2番目の値が7ではなく100

私は何をしないのですなると予想しているのでしょうか?これは今、何を期待し

template<class T> 
void f2(T arg) 
{ 
    arg.get() = xx; 
} 

f2

+16

参照ラッパーは再シール可能であるため、参照先のオブジェクトではなく、参照先のオブジェクトに変更が加えられます。 –

+1

優秀な質問! – vsoftco

答えて

56

小さな変更は、手掛かりを提供します。

これは、std::refstd::reference_wrapper<>オブジェクトを返すために発生しました。代入演算子は、ラッパーにをバインドします。 (http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3Dを参照)

ラップされた参照には割り当てません。 f1場合

std::reference_wrapper<T>operator+暗黙のint秒の暗黙の右側に結合するT&への変換演算子を提供するため、あなたは予想通り、すべてが働いています。

+1

あなたは仕事が必要ですか? – Ramy

+0

さて、ありがとう – Ramy

11

reference_wrapperoperator =であり、非明示的なコンストラクタはdocumentationを参照してください。

f2xxにローカルreference_wrapperを再バインド:

だから、それは驚くべきことであるとしても、それは正常な動作です。

8

arg = xx;

ローカルargxx(と結合すると読む)を指します。 (そして、これ以上jを指す)

arg += xx;

暗黙operator T&()operator +=の引数と一致するように適用され、したがって、加算が参照されるオブジェクト、すなわちj上で実行されます。

したがって、観察された動作は正しいです。

関連する問題