Ir para o conteúdo

Ú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.

Status status(transportDetail);
auto result = Unwrap(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

Comentários