2013-07-02 2 views
19

나는 다음과 같은 코드가 있습니다표준 : : 바인딩은 참조를 잃지

#include <stdio.h> 
#include <functional> 

template <typename T> 
auto callback(T&& func) ->decltype(func()) 
{ 
    return func(); 
} 

double test(double& value) 
{ 
    value=value+1.0; 
    return value; 
} 

int main(void) 
{ 
    double t=1.0; 
    printf("%f\n",t); 
    test(t); 
    printf("%f\n",t); 
    callback(std::bind(test,t)); 
    printf("%f\n",t); 
} 

을 그리고 그것은 callback 기능을 의미

1.000000 
2.000000 
2.000000 

대신 t의 사본을 가지고 출력 t을 참조하십시오. 나는 std::bind 때문에 완벽하게 전달되어야하므로 무슨 일이 일어 났는지 궁금합니다.

답변

33

std::bind은 기본적으로 값 의미론을 사용합니다. 그것은 당신이 안전하게 다음과 같은 일을 할 수있게 해주는 정상적인 것입니다.

int f(double x); 

auto fun = std::bind(f, 1.0); // stores a copy, not a reference to a temporary 
fun(); 

값 의미를 사용하는 것이 안전합니다. 바인드 된 인수의 수명은 bind에 의해 반환 된 객체의 수명이됩니다. 참조 의미를 사용하는 것은 그 보증을하지 못합니다. 그래서 당신은 참조 시맨틱을 원할 때 명시 적이어야한다. 문제가 생기면 그건 당신 잘못입니다. 위해서는 당신이 std::ref를 사용할 필요가해야 할 일 :

int main(void) 
{ 
    double t=1.0; 
    printf("%f\n",t); 
    test(t); 
    printf("%f\n",t); 
    callback(std::bind(test, std::ref(t))); 
    printf("%f\n",t); 
} 

이 같은 프로토콜은 std::thread 생성자와 같은 표준 라이브러리의 다른 곳에서 사용된다.

8

std::bind()은 값 의미 (as R. Martinho Fernandes nicely explains in his answer)로 설계되었으며 으로 내부적으로 복사본을 만듭니다. 당신이 원하는/필요한 것은 std::ref입니다 :

callback(std::bind(test, std::ref(t))); 
//      ^^^^^^^^^^^ 

std::ref 원래 인수에 대한 참조를 랩하는 std::reference_wrapper<> 개체를 반환합니다. 이렇게하면 t 주변의 reference_wrapper 개체가 복사되고 t 자체는 복사되지 않습니다.

값 의미 (기본적으로 가정)와 참조 의미 (사용자의 명시적인 개입이 필요함) 중에서 선택할 수 있습니다.

여기는 live example입니다.