Última atualização:2026-10-12
ref e reference_wrapper em C++¶
Compreendendo a fundo std::cref, std::ref e std::reference_wrapper em C++¶
Na programação em C++, às vezes precisamos passar referências sem fazer cópias, ou usar objetos constantes em lugares que exigem referências. Para resolver esses problemas, a biblioteca padrão do C++ oferece três ferramentas úteis: std::cref, std::ref e std::reference_wrapper. Este artigo explora em profundidade a finalidade, as diferenças e as aplicações práticas dessas ferramentas.
Além disso, sabemos que, na linguagem Rust, o método Unwrap é frequentemente implementado; como implementá-lo em C++?
Para isso, vamos nos basear no código do Apache arrow, que tem este trecho:
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));
}
Em seguida, podemos chamar assim para extrair o TransportStatusDetail realmente contido no Status.
Vamos examinar por vários ângulos e, por fim, apresentar o código completo da Demo.
1. std::cref: criando referências constantes¶
std::cref é uma função template usada para criar uma referência a um objeto constante. Ela retorna um objeto std::reference_wrapper, que pode ser usado onde uma referência é exigida. Isso é particularmente útil na passagem de parâmetros de funções, pois nos permite passar objetos constantes sem fazer cópias, mantendo a semântica de referência.
Exemplo:
#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: criando referências modificáveis¶
Diferente do std::cref, std::ref é uma função template usada para criar uma referência a um objeto modificável. Ela retorna um objeto std::reference_wrapper, que pode ser usado onde uma referência é exigida, permitindo também modificar o objeto referenciado.
Exemplo:
#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: um wrapper de referências¶
std::reference_wrapper é uma classe template usada para envolver referências, permitindo que sejam armazenadas em contêineres ou passadas em forma de referência. Ela oferece uma sintaxe semelhante à de referências e pode ser usada com os contêineres padrão, já que os contêineres não conseguem armazenar referências diretamente.
Exemplo:
#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;
}
Neste exemplo, std::reference_wrapper nos permite envolver referências em um contêiner e, em seguida, acessar e modificar o valor dos objetos originais por meio do método get().
4.Demo do Unwrap¶
Aqui está o trecho de código específico; o código completo está no conteúdo do Planeta do Conhecimento.
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;
}
Seja bem-vindo a explorar junto C++那些事; para mais projetos/conteúdos, junte-se ao Planeta do Conhecimento.
Tópicos relacionados¶
- Funções virtuais puras e classes abstratas em C++ | C++那些事
- Asserções com assert em C++ | C++那些事
- Bit fields em C++ | C++那些事
- Implementando polimorfismo de C++ em linguagem C | C++那些事
- Constantes e modificadores com const em C++ | C++那些事
- A família completa do const em C++ | C++那些事
- O operador de desreferência * em C++ | C++那些事
- Inicialização e atribuição em C++ | C++那些事
- Formas de retornar múltiplos valores em C++ | C++那些事
- A palavra-chave mutable em C++ | C++那些事