개념

  • std::reference_wrapper는 참조를 값처럼 복사하고 전달할 수 있게 만들어주는 래퍼
  • 내부적으로 포인터를 저장하고, 변환 연산자와 get() 함수를 통해 raw referecne로 암시적 변환 가능
  • C++11에서 도입됨

기본 구조

  template<typename T> 
class reference_wrapper
{
    T* pobj{};
public:
    reference_wrapper(T& obj) : pobj{&obj} {}
    operator T&() const { return *pobj;}
    T& get() const { return *pobj;}
};

int main()
{
    int n = 10;
    reference_wrapper r1{n};
    int& r2 = r1;
    int& r3 = r1.get();
}
  

예제

  int n = 10;
std::reference_wrapper r1{n};
int& r2 = r1;         // 암시적 변환
int& r3 = r1.get();   // 명시적 접근
  

callable 객체로 사용 가능

  • operator()를 재정의한 객체에 대한 참조를 감쌀 경우, reference_wrapper 자체가 함수처럼 호출 가능
  int add(int a, int b) { return a + b; }
std::reference_wrapper f{add};
int n = f(1, 2); // f.operator()(1, 2)
  

생성 방법

  int n = 10;
std::reference_wrapper r1{n};
std::reference_wrapper<int> r2{n};
std::reference_wrapper<const int> r3{n};

r1.get() = 20; // ok
r2.get() = 20; // ok
// r3.get() = 20; // error (const)

// 편의 함수 사용
auto r4 = std::ref(n);   // r1과 같음
auto r5 = std::cref(n);  // r3과 같음
  

활용

  • 값으로 설계된 함수에서 참조를 전달하고 싶을 때 유용함
  • std::ref 또는 std::reference_wrapper를 사용하면 참조를 값처럼 전달 가능

예제: 참조 전달 유지

  void foo(int& r) { r = 100; }

template<typename F, typename T>
void log_and_call(F f, T arg) {
    f(arg);
}

int main() {
    int n = 0;
    log_and_call(foo, std::ref(n)); // n이 수정됨
}
  

위의 예시와 같은 설계 이유

  • call by value로 설계하는 것이 더 안전해서
  • bind, ref로 쓰면 파괴되지않게 유의해야 함함