Última actualización:2026-10-12
ref y reference_wrapper en C++¶
Comprensión profunda de std::cref, std::ref y std::reference_wrapper en C++¶
En la programación en C++, a veces necesitamos pasar referencias sin realizar copias, o usar objetos constantes donde se requiere una referencia. Para resolver estos problemas, la biblioteca estándar de C++ ofrece tres herramientas útiles: std::cref, std::ref y std::reference_wrapper. Este artículo examina en profundidad el uso de estas herramientas, sus diferencias y sus aplicaciones prácticas.
Además, sabemos que en el lenguaje Rust se implementa con frecuencia un método Unwrap; ¿cómo implementarlo en C++?
Para ello nos referimos al código de Apache arrow, que contiene este fragmento:
std::optional<std::reference_wrapper<const TransportStatusDetail>>
TransportStatusDetail::Unwrap(const Status& status) {
std::shared_ptr<StatusDetail> detail = status.detail();
if (!detail) return std::nullopt;
if (detail->type_id() != kTypeId) return std::nullopt;
return std::cref(arrow::internal::checked_cast<const TransportStatusDetail&>(*detail));
}
Después podremos llamarlo de esta manera y extraer el TransportStatusDetail real que hay dentro del Status.
Veámoslo desde varios ángulos y, al final, se incluye el código completo de la Demo.
1. std::cref: crear una referencia constante¶
std::cref es una función plantilla que sirve para crear una referencia a un objeto constante. Devuelve un objeto std::reference_wrapper, que puede usarse donde se necesite una referencia. Esto es especialmente útil al pasar parámetros a funciones, porque nos permite pasar objetos constantes sin copiarlos, conservando la semántica de las referencias.
Ejemplo:
#include <iostream>
#include <functional>
void printValue(const int& value) {
std::cout << "Value: " << value << std::endl;
}
int main() {
int number = 42;
auto crefNumber = std::cref(number);
printValue(crefNumber); // 使用常量引用传递参数
return 0;
}
2. std::ref: crear una referencia modificable¶
A diferencia de std::cref, std::ref es una función plantilla que sirve para crear una referencia a un objeto modificable. Devuelve un objeto std::reference_wrapper, que permite usarla donde se necesite una referencia y, al mismo tiempo, modificar el objeto referenciado.
Ejemplo:
#include <iostream>
#include <functional>
void modifyValue(int& value) {
value *= 2;
}
int main() {
int number = 42;
auto refNumber = std::ref(number);
modifyValue(refNumber); // 使用可修改的引用作为参数
std::cout << "Modified Value: " << number << std::endl;
return 0;
}
3. std::reference_wrapper: un envoltorio de referencias¶
std::reference_wrapper es una clase plantilla que sirve para envolver referencias de modo que puedan almacenarse en contenedores o pasarse en forma de referencia. Ofrece una sintaxis similar a la de las referencias y puede usarse con los contenedores estándar, ya que estos no pueden almacenar referencias directamente.
Ejemplo:
#include <iostream>
#include <vector>
#include <functional>
int main() {
int number1 = 42;
int number2 = 73;
std::vector<std::reference_wrapper<int>> numbers = {std::ref(number1), std::ref(number2)};
for (auto& num : numbers) {
num.get() += 10; // 修改原始对象的值
}
std::cout << "Number 1: " << number1 << std::endl;
std::cout << "Number 2: " << number2 << std::endl;
return 0;
}
En este ejemplo, std::reference_wrapper nos permite envolver referencias en un contenedor y luego acceder al valor de los objetos originales y modificarlo mediante el método get().
4. Demo de Unwrap¶
Aquí se muestra el fragmento de código concreto; el código completo se encuentra en el contenido del Planeta de Conocimiento (知识星球).
std::optional<std::reference_wrapper<const TransportStatusDetail>> Unwrap(const Status& status) {
std::shared_ptr<StatusDetail> detail = status.detail();
if (!detail) return std::nullopt;
if (detail->type_id() != kTypeId) return std::nullopt;
return std::cref(static_cast<const TransportStatusDetail&>(*detail));
}
int main() {
// 创建 TransportStatusDetail 对象
std::shared_ptr<StatusDetail> transportDetail = std::make_shared<TransportStatusDetail>();
// 创建 Status 对象并传入 TransportStatusDetail 对象
Status status(transportDetail);
auto result = Unwrap(status);
if (result) {
const TransportStatusDetail& detail = result.value().get();
// 使用 detail 进行操作
std::cout << "TransportStatusDetail found." << std::endl;
} else {
std::cout << "No valid TransportStatusDetail found." << std::endl;
}
return 0;
}
Bienvenido a explorar juntos C++那些事; para más proyectos/contenido, únete al Planeta de Conocimiento (知识星球).
Temas relacionados¶
- Funciones virtuales puras y clases abstractas en C++ | C++那些事
- Aserciones assert en C++ | C++那些事
- Campos de bits en C++ | C++那些事
- Implementar el polimorfismo de C++ en lenguaje C | C++那些事
- const en C++: constantes y modificación | C++那些事
- La familia completa de const en C++ | C++那些事
- El operador de desreferencia * en C++ | C++那些事
- Inicialización y asignación en C++ | C++那些事
- Formas de devolver varios valores en C++ | C++那些事
- La palabra clave mutable en C++ | C++那些事