前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 多值返回:从版本1到版本6秒杀​

C++ 多值返回:从版本1到版本6秒杀​

作者头像
公众号guangcity
发布2024-01-10 16:19:41
1360
发布2024-01-10 16:19:41
举报
文章被收录于专栏:光城(guangcity)光城(guangcity)

C++ 多值返回:从版本1到版本6秒杀

  • 1. 指针与引用
  • 2. Tuple + Tie
  • 3. Struct Binding
  • 4. 函数 Callback
  • 5. 自定义 Out
  • 6. 模版推导

今天再提出一个比较经典的面试题:函数如何返回多个结果?你能想到几种办法?

其实这道题目考察的知识点非常的多,涉及到:

  • 指针
  • 引用
  • lambda
  • functional
  • tie
  • tuple
  • struct bingding
  • template deduce
  • 等等

本篇文章将会给大家用不同的方法来解答这道题目,首先我们转化一下这个题目,使用a / b来模拟(下面不考虑被除数为0的场景),返回商与余数。简单来说转化为一个函数返回商与余数有多少种办法?

下面进入正文,注:本节的所有代码已首发于星球,感兴趣戳下方二维码即可。

1. 指针与引用

对接口进行更改,添加两个变量,使用指针与引用。

代码语言:javascript
复制
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;
}

使用这种方式的缺点也明显可见,当返回值不止两个,接口就非常的长。此外,如果面试官要求你不允许更改函数接口,那么这个办法用不了了。

2. Tuple + Tie

Tuple和tie的组合为函数返回多个值提供了一种简洁的方式。通过使用std::tie,我们可以将tuple中的元素解包到不同的变量中,提高代码的清晰度。

这种方法算是标准答案之一,比较简单清晰,如果返回值是两个pair也可以。

代码语言:javascript
复制
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

对上面进行改造,C++17引入的结构化绑定进一步简化了多值返回的代码。使用auto和结构化绑定,使得代码更加直观易懂。

如果面试官要你进一步的对上面的方法进行改造,那么可以变为下面这个代码示例,使用结构化绑定使代码更加优雅。

代码语言:javascript
复制
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

在日常项目中,特别是一些开源项目,callback是一种常用的手段,通过传递处理返回值的callback,让用户自定义处理,这样便实现了返回多个值,实现更加灵活的代码结构。这对于异步编程和事件处理等场景非常有用。

代码语言:javascript
复制
void divide(int dividend, int divisor, std::function<void(int, int)> callback) {
  callback(dividend / divisor, dividend % divisor);
}

5. 自定义 Out

自定义out是一种通过结构体包装的方式,将输出参数作为结构体的成员。这种方式提高了代码的可读性,尤其适用于需要返回多个值的函数。

代码语言:javascript
复制
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. 模版推导

C++的模版推导为开发者提供了更为灵活和简洁的代码编写方式。通过模版推导,我们可以处理不同类型的数据而无需显式指定类型。

代码语言:javascript
复制
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);

总体而言,C++提供了多种方式来实现多值返回,每种方式都有其适用的场景。选择合适的方式取决于具体的需求,开发者可以根据代码结构和可读性来灵活使用这些特性。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++ 多值返回:从版本1到版本6秒杀
    • 1. 指针与引用
      • 2. Tuple + Tie
        • 3. Struct Binding
          • 4. 函数 Callback
            • 5. 自定义 Out
              • 6. 模版推导
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档