std::reference_wrapper


std::reference_wrapper

std::reference_wrapper is a class template in C++ that wraps a reference in a copyable, assignable object. It provides a way to store references in standard containers and use them in situations where references are not directly supported.

Example 1: Basic Usage

#include <functional>
#include <iostream>

int main() {
    int x = 10;
    std::reference_wrapper<int> ref = x;

    std::cout << "Value: " << ref << std::endl;

    ref.get() = 20;
    std::cout << "Updated value: " << x << std::endl;

    return 0;
}

Explanation

Example 2: Storing References in Containers

#include <functional>
#include <vector>
#include <iostream>

int main() {
    int a = 1, b = 2, c = 3;
    std::vector<std::reference_wrapper<int>> vec = {a, b, c};

    for (auto& ref : vec) {
        std::cout << ref << " ";
        ref.get() *= 2;
    }
    std::cout << std::endl;

    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;

    return 0;
}

Explanation

Example 3: Using with Algorithms

#include <functional>
#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> numbers = {5, 2, 8, 1, 9};
    std::vector<std::reference_wrapper<int>> refs(numbers.begin(), numbers.end());

    std::sort(refs.begin(), refs.end(), 
              [](const int& a, const int& b) { return a > b; });

    for (const auto& ref : refs) {
        std::cout << ref << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation

Summary

std::reference_wrapper is a powerful tool in C++ that allows references to be treated as objects, enabling their use in contexts where references are not directly supported, such as in standard containers. It provides a way to maintain reference semantics while allowing for copyability and assignability. Key points to remember:

  1. It wraps references in a copyable, assignable object.
  2. It allows storing references in standard containers.
  3. It can be implicitly converted back to a reference of the wrapped type.
  4. The get() member function provides access to the wrapped reference.
  5. It's useful in algorithms and situations where you need to treat references as objects.

std::reference_wrapper is particularly useful when working with legacy code or APIs that expect value types but you want to pass references, or when you need to store references in standard containers.

Citations: [1] https://stackoverflow.com/questions/26766939/what-is-the-difference-between-stdreference-wrapper-and-a-simple-pointer [2] https://learn.microsoft.com/en-us/cpp/standard-library/reference-wrapper-class?view=msvc-170 [3] https://www.nextptr.com/tutorial/ta1441164581/stdref-and-stdreference_wrapper-common-use-cases [4] https://stackoverflow.com/questions/18127469/how-to-correctly-use-stdreference-wrappers [5] https://www.reddit.com/r/cpp/comments/pt9o1j/stdreference_wrappert_instead_of_ptr_for_not/ [6] https://www.learncpp.com/cpp-tutorial/arrays-of-references-via-stdreference_wrapper/ [7] https://www.sololearn.com/en/Discuss/2840738/someone-explain-about-reference_wrapper-in-c [8] https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

Related - How does std::reference_wrapper improve performance in certain scenarios - Can you provide examples of using std::reference_wrapper with std::bind - What are the key differences between std::ref and std::cref - How does std::reference_wrapper handle reassignment - Are there any limitations or pitfalls when using std::reference_wrapper

Why store a reference in a standard container rather than an object or a pointer?

Storing references in standard containers using std::reference_wrapper can be beneficial in several scenarios:

  1. Avoiding object copies: When you want to store large objects in a container without copying them, std::reference_wrapper allows you to store references instead[1]. This can be more efficient in terms of memory usage and performance.

  2. Maintaining original object state: By storing references, any modifications made through the container will affect the original objects, which can be desirable in certain situations[3].

  3. Working with non-copyable objects: Some objects may not be copyable (e.g., streams or unique resources). std::reference_wrapper allows you to store references to these objects in containers[2].

  4. Polymorphic behavior: When working with inheritance hierarchies, storing references can preserve polymorphic behavior, which is not possible with object copies[3].

  5. Flexibility in algorithms: std::reference_wrapper allows you to use references with algorithms that typically work with value semantics, providing more flexibility in how you manipulate data[1].

  6. Avoiding pointer management: Unlike raw pointers, std::reference_wrapper cannot be null or invalid, providing a safer alternative when you need reference semantics[8].

  7. Enabling assignability for classes with reference members: Using std::reference_wrapper instead of regular references for class members allows the class to remain assignable and movable[8].

Here's an example demonstrating the use of std::reference_wrapper with a container:

#include <vector>
#include <functional>
#include <iostream>

int main() {
    int a = 1, b = 2, c = 3;
    std::vector<std::reference_wrapper<int>> vec = {a, b, c};

    for (auto& ref : vec) {
        std::cout << ref << " ";
        ref.get() *= 2;
    }
    std::cout << std::endl;

    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;

    return 0;
}

This code creates a vector of references to integers, allowing you to modify the original variables through the container[2].

While std::reference_wrapper provides these benefits, it's important to ensure that the lifetime of the referenced objects exceeds that of the container to avoid dangling references. In many cases, using pointers or smart pointers might be more appropriate, especially when dealing with dynamic lifetimes or optional values.

Citations:

[1] https://bolu.dev/programming/2024/05/30/forward-ref.html [2] https://isocpp.org/blog/2020/07/stdref-and-stdreference_wrapper-common-use-cases-nextptr [3] https://www.machinet.net/tutorial-eng/when-and-how-to-use-std-reference-wrapper-in-cpp [4] https://stackoverflow.com/questions/7058339/when-should-i-use-pointers-instead-of-references-in-api-design [5] https://www.reddit.com/r/cpp/comments/ezwij0/when_to_use_a_reference_type_versus_a_pointer/ [6] https://stackoverflow.com/questions/26766939/what-is-the-difference-between-stdreference-wrapper-and-a-simple-pointer [7] https://www.justsoftwaresolutions.co.uk/cplusplus/reference_wrappers_explained.html [8] https://www.nextptr.com/tutorial/ta1441164581/stdref-and-stdreference_wrapper-common-use-cases

Previous Page | Course Schedule | Course Content