std::ref
is a powerful and flexible feature in the C++(STL) standard library, introduced in C++11.
It is used to create objects that act as references, allowing values to be passed by reference in scenarios where the default behavior is to create copies. This feature is especially useful in contexts such as multithreading, STL algorithms, and lambdas.
In C++, when we pass arguments to functions or higher-order functions (such as lambdas or std::bind
), the values are usually copied. However, in many situations it may be desirable to pass the argument by reference to avoid unnecessary copying or modifying the original variable.
std::ref
solves this by creating a “wrapped reference” that ensures that the variable is treated as a reference and not a copy.
std::ref
returns an object of type std::reference_wrapper
, which acts as a container for the reference to the original object. This container complies with the requirements for function arguments and can be used transparently in many situations.
The required header to use std::ref
is:
#include <functional>
#include <iostream>
#include <functional>
void increment(int& value){
value++; }
int main(){
int x = 10;
// Using std::ref to pass x by reference
auto lambda = [&](){
increment(std::ref(x));
};
lambda();
std::cout << "Value of x: " << x << std::endl; // Output: Value of x: 11
return EXIT_SUCCESS;
}
std::ref
with std::bindstd::bind
is a higher-order function that allows you to create partially applied functions. By default, it copies the arguments provided. However, we can use std::ref
to avoid this.
#include <iostream>
#include <functional>
void print_and_increment(int& value){
std::cout << "Value: " << value << '\n';
++value;
}
int main(){
int x = 5;
auto bound_function = std::bind(print_and_increment, std::ref(x));
bound_function();
std::cout << "New value of x: " << x << '\n'; // Output: New value of x: 6
return EXIT_SUCCESS;
}
std::ref
is useful when working with STL containers that require copies of the elements, such as std::vector
.
#include <iostream>
#include <vector>
#include <functional>
int main(){
int x = 1, y = 2, z = 3;
// Creating a vector of references
std::vector<std::reference_wrapper<int>> refs = {std::ref(x), std::ref(y), std::ref(z)};
for(auto& ref : refs){
ref.get() += 10; // Modify the original values
}
std::cout << "x: " << x << ", y: " << y << ", z: " << z << '\n';
// Output: x: 11, y: 12, z: 13
return EXIT_SUCCESS;
}
std::ref
should not be used with temporary types, since the referenced object needs to survive for the lifetime of the encapsulated reference.std::cref
, which works similarly to std::ref
, but ensures that the referenced object is treated as const
.std::reference_wrapper
can be converted back to a normal reference using the get()
method.int a = 42;
std::reference_wrapper<int> ref = std::ref(a);
ref.get() = 50; // Modifies the original value
auto b = ref.get();
std::ref
is a powerful tool for flexibly handling references in C++. It helps to avoid unnecessary copies and is essential in scenarios that require the use of arguments by reference. Understanding its use can significantly improve the efficiency and clarity of your code.