Ir para o conteúdo

Última atualização:2026-10-12

Formas de retornar múltiplos valores em C++

Hoje trago mais uma pergunta clássica de entrevista: como uma função pode retornar vários resultados? Quantos métodos você consegue imaginar?

Na verdade, essa questão avalia muitos pontos de conhecimento, envolvendo:

  • Ponteiros
  • Referências
  • lambda
  • functional
  • tie
  • tuple
  • struct binding
  • template deduce
  • entre outros

Este artigo responderá à pergunta usando métodos diferentes. Primeiro, reformulemos o problema: use a / b para simular (abaixo, sem considerar o caso de divisor 0) e retorne quociente e resto. Em resumo: de quantas maneiras uma função pode retornar o quociente e o resto?

Vamos ao conteúdo principal. Nota: todos os códigos desta seção foram publicados primeiro no Planeta do Conhecimento; se tiver interesse, escaneie o QR code abaixo.

1. Ponteiros e referências

Altere a interface, adicionando duas variáveis, usando ponteiros e referências.

void divideWithReferences(int dividend, int divisor, int& quotient, int& remainder) {
  quotient = dividend / divisor;
  remainder = dividend % divisor;
}

void divideWithPointers(int dividend, int divisor, int* quotient, int* remainder) {
  if (quotient) *quotient = dividend / divisor;
  if (remainder) *remainder = dividend % divisor;
}

As desvantagens dessa abordagem são evidentes: quando há mais de dois valores de retorno, a interface fica muito longa. Além disso, se o entrevistador exigir que a interface da função não seja alterada, esse método não poderá ser usado.

2. Tuple + Tie

A combinação de tuple e tie oferece uma forma concisa de uma função retornar vários valores. Ao usar std::tie, podemos desempacotar os elementos do tuple em variáveis diferentes, melhorando a clareza do código.

Esse método pode ser considerado uma das respostas padrão: é simples e claro; se os valores retornados forem dois, um pair também serve.

std::tuple<int, int> divide(int dividend, int divisor) {
    return std::make_tuple(dividend / divisor, dividend % divisor);
}


std::tie(quotient, remainder) = divide(14, 3);
std::cout << quotient << ", " << remainder << std::endl;

3. Struct Binding

Refinando o anterior, o structured binding introduzido no C++17 simplifica ainda mais o código de retorno de múltiplos valores. Usando auto e structured binding, o código fica mais intuitivo e fácil de entender.

Se o entrevistador pedir para você melhorar ainda mais o método acima, ele pode se tornar o exemplo de código a seguir, usando structured binding para deixar o código mais elegante.

auto divide(int dividend, int divisor) {
  struct result {
    int quotient;
    int remainder;
  };
  return result{dividend / divisor, dividend % divisor};
}
auto [quotient, remainder] = divide(14, 3);

4. Callback de função

Em projetos do dia a dia, especialmente em projetos de código aberto, o callback é um recurso muito usado: passando um callback que processa os valores retornados, o usuário define o processamento como quiser, realizando assim o retorno de múltiplos valores e tornando a estrutura do código mais flexível. Isso é muito útil em cenários como programação assíncrona e tratamento de eventos.

void divide(int dividend, int divisor, std::function<void(int, int)> callback) {
  callback(dividend / divisor, dividend % divisor);
}

5. Out personalizado

O out personalizado é uma abordagem que envolve os parâmetros de saída como membros de uma estrutura. Esse método melhora a legibilidade do código e é especialmente adequado para funções que precisam retornar vários valores.

template <class T>
struct out {
  std::function<void(T)> target;

  out(T* t)
      : target([t](T&& in) {
          if (t) *t = std::move(in);
        }) {}

  template <class... Args>
  void emplace(Args&&... args) {
    target(T(std::forward<Args>(args)...));
  }

  template <class X>
  void operator=(X&& x) {
    emplace(std::forward<X>(x));
  }

  template <class... Args>
  void operator()(Args&&... args) {
    emplace(std::forward<Args>(args)...);
  }
};

void divide(int dividend, int divisor, out<int>& quotient_out, out<int>& remainder_out) {
  quotient_out.emplace(dividend / divisor);
  remainder_out.emplace(dividend % divisor);
}

6. Dedução de templates

A dedução de templates do C++ oferece aos desenvolvedores uma forma mais flexível e concisa de escrever código. Com ela, podemos tratar dados de tipos diferentes sem especificar os tipos explicitamente.

template <typename T1, typename T2>
struct many {
  T1 quotient;
  T2 remainder;
};

template <class T1, class T2>
many(T1, T2) -> many<T1, T2>;

many<int, int> divide(int dividend, int divisor) {
  return many{
      dividend / divisor,
      dividend % divisor,
  };
}

auto [quotient, remainder] = divide(14, 3);

De modo geral, o C++ oferece várias formas de implementar o retorno de múltiplos valores, cada uma com seus cenários de aplicação. A escolha adequada depende das necessidades concretas; os desenvolvedores podem usar essas características com flexibilidade, conforme a estrutura e a legibilidade do código.

Tópicos relacionados

Comentários