developer tip

C ++ std :: ref (T)와 T &의 차이점은 무엇입니까?

copycodes 2020. 10. 29. 08:17
반응형

C ++ std :: ref (T)와 T &의 차이점은 무엇입니까?


이 프로그램에 대해 몇 가지 질문이 있습니다.

#include <iostream>
#include <type_traits>
#include <functional>
using namespace std;
template <typename T> void foo ( T x )
{
    auto r=ref(x);
    cout<<boolalpha;
    cout<<is_same<T&,decltype(r)>::value;
}
int main()
{
    int x=5;
    foo (x);
    return 0;
}

출력은 다음과 같습니다.

false

std::ref객체의 참조를 반환하지 않으면 무엇을하는지 알고 싶습니다 . 기본적으로 다음의 차이점은 무엇입니까?

T x;
auto r = ref(x);

T x;
T &y = x;

또한이 차이가 존재하는 이유를 알고 싶습니다. 우리가 참조 가 필요 std::ref하거나 std::reference_wrapper(예 :) 때 T&필요한가?


Well ref은 객체에 reference_wrapper대한 참조를 보유하기 위해 적절한 유형의 객체를 생성합니다. 즉, 신청할 때 :

auto r = ref(x);

이것은 (즉 )에 reference_wrapper대한 직접 참조가 아닌 a를 반환합니다 . 이것은 (즉 ) 대신 유지 됩니다.xT&reference_wrapperrT&

A reference_wrapperreference복사 할 수있는 객체 를 에뮬레이션하려는 경우 매우 유용합니다 ( 복사 구성 가능복사 할당 가능 ).

C에서 + +, 당신은 참조 (예를 들어 생성되면 y객체 (말을) x한 후,) yx같은 공유 기본 주소를 . 또한 y다른 개체를 참조 할 수 없습니다. 또한 참조 배열을 만들 수 없습니다. 즉, 다음과 같은 코드에서 오류가 발생합니다.

#include <iostream>
using namespace std;

int main()
{
    int x=5, y=7, z=8;
    int& arr[] {x,y,z};    // error: declaration of 'arr' as array of references
    return 0;
}

그러나 이것은 합법적입니다.

#include <iostream>
#include <functional>  // for reference_wrapper
using namespace std;

int main()
{
    int x=5, y=7, z=8;
    reference_wrapper<int> arr[] {x,y,z};
    for (auto a: arr)
        cout << a << " ";
    return 0;
}
/* OUTPUT:
5 7 8
*/

의 문제에 대해 이야기 cout << is_same<T&,decltype(r)>::value;하면 해결책은 다음과 같습니다.

cout << is_same<T&,decltype(r.get())>::value;  // will yield true

프로그램을 보여 드리겠습니다.

#include <iostream>
#include <type_traits>
#include <functional>
using namespace std;

int main()
{
    cout << boolalpha;
    int x=5, y=7;
    reference_wrapper<int> r=x;   // or auto r = ref(x);
    cout << is_same<int&, decltype(r.get())>::value << "\n";
    cout << (&x==&r.get()) << "\n";
    r=y;
    cout << (&y==&r.get()) << "\n";
    r.get()=70;
    cout << y;
    return 0;
}
/* Ouput:
true
true
true
70
*/

여기에서 우리는 세 가지를 알게됩니다.

  1. A reference_wrapper object (here r) can be used to create an array of references which was not possible with T&.

  2. r actually acts like a real reference (see how r.get()=70 changed the value of y).

  3. r is not same as T& but r.get() is. This means that r holds T& ie as its name suggests is a wrapper around a reference T&.

I hope this answer is more than enough to explain your doubts.


std::reference_wrapper is recognized by standard facilities to be able to pass objects by reference in pass-by-value contexts.

For example, std::bind can take in the std::ref() to something, transmit it by value, and unpacks it back into a reference later on.

void print(int i) {
    std::cout << i << '\n';
}

int main() {
    int i = 10;

    auto f1 = std::bind(print, i);
    auto f2 = std::bind(print, std::ref(i));

    i = 20;

    f1();
    f2();
}

This snippet outputs :

10
20

The value of i has been stored (taken by value) into f1 at the point it was initialized, but f2 has kept an std::reference_wrapper by value, and thus behaves like it took in an int&.


A reference (T& or T&&) is a special element in C++ language. It allows to manipulate an object by reference and has special use cases in the language. For example, you cannot create a standard container to hold references: vector<T&> is ill formed and generates a compilation error.

A std::reference_wrapper on the other hand is a C++ object able to hold a reference. As such, you can use it in standard containers.

std::ref is a standard function that returns a std::reference_wrapper on its argument. In the same idea, std::cref returns std::reference_wrapper to a const reference.

One interesting property of a std::reference_wrapper, is that it has an operator T& () const noexcept;. That means that even if it is a true object, it can be automatically converted to the reference that it is holding. So:

  • as it is a copy assignable object, it can be used in containers or in other cases where references are not allowed
  • thanks to its operator T& () const noexcept;, it can be used anywhere you could use a reference, because it will be automatically converted to it.

참고URL : https://stackoverflow.com/questions/33240993/c-difference-between-stdreft-and-t

반응형