
本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身。
文章结尾有最新热度的文章,感兴趣的可以去看看。
文章有点长(2169字阅读时长:5分),期望您能坚持看完,并有所收获
大家好,今天我继续给大家分享干货。熟悉我的人,都知道我真正的干货一般在中间和末尾部分(文章中间部分:有项目文字和视频介绍)。请耐心看完!谢谢。您可以在文章末尾处获取完整的源代码文件。

今天,咱们来探讨一个经典的面试问题:一个函数如何返回多个结果呢?你能想出几种方法?
实际上,这个问题涵盖了众多知识点,其中包括:
本文将探究回答这个问题的不同方法。首先,咱们把问题具体化,以 a / b 为例(暂不考虑除数为零的情况),要同时返回商和余数。简单来说,我们有多少种方式可以编写一个能同时返回商和余数的函数呢?
现在,让我们深入探讨具体内容。

通过添加两个变量并使用指针和引用来修改函数接口。
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;
}
这种方法的缺点很明显,当返回值超过两个时,函数接口会变得冗长。此外,如果面试官禁止修改函数接口,这种方法就不可行了。
std::tuple 和 std::tie 的组合提供了一种简洁的方式,可从函数中返回多个值。通过使用 std::tie,我们可以将元组的元素解包到不同的变量中,从而提高代码的清晰度。
这种方法被认为是标准答案之一,既简单又清晰。它在返回两个值时也同样适用。
std::tuple<int, int> divide(int dividend, int divisor) {
return std::make_tuple(dividend / divisor, dividend % divisor);
}
int quotient, remainder;
std::tie(quotient, remainder) = divide(14, 3);
std::cout << quotient << ", " << remainder << std::endl;
在前面方法的基础上,C++17 引入了结构化绑定,进一步简化了多值返回的代码。使用 auto 和结构化绑定能让代码更加直观。
如果面试官要求对前面的方法进行进一步优化,可以将代码转换为以下示例,使用结构化绑定让代码结构更优雅。
auto divide(int dividend, int divisor) {
struct result {
int quotient;
int remainder;
};
return result{dividend / divisor, dividend % divisor};
}
auto [quotient, remainder] = divide(14, 3);
在日常项目,尤其是开源项目中,回调是一种常用的机制。通过传递一个处理返回值的回调函数,用户可以自定义处理方式,使代码结构更加灵活。这在异步编程和事件处理等场景中特别有用。
void divide(int dividend, int divisor, std::function<void(int, int)> callback) {
callback(dividend / divisor, dividend % divisor);
}
自定义输出封装是将输出参数封装在一个结构体中的方法。这种方法提高了代码的可读性,尤其适用于需要返回多个值的函数。
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);
}
C++ 的模板推导为开发者提供了一种更灵活、简洁的代码编写方式。通过模板推导,我们可以处理不同的数据类型,而无需显式指定它们。
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++ 提供了多种实现多值返回的方法,每种方法都有其适用的场景。方法的选择取决于具体需求,开发者可以根据代码结构和可读性灵活运用这些特性。以上就是我的分享。这些分析皆源自我的个人经验,希望上面分享的这些东西对大家有帮助,感谢大家!
Stroustrup, Bjarne. 《The C++ Programming Language》
ISO/IEC 14882:2017 《Programming Language C++》
Meyers, Scott. 《Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14》

最新热门文章推荐:
借助C++OpenCV图像背景替换:老办法束手无策,新方案如何出奇制胜?
DeepSeek优势探秘:传统训练成本高,它如何凭优势改写大模型发展走向?
从无名到C++大神,赫布·萨特(Herb Sutter)如何逆袭?
C++OpenCV实现实时模板匹配算法:老办法匹配已过气,实时识别有何高招?
C++OpenCV实时二维码识别:传统扫码已过时,实时捕捉有何奇招?
C++ OpenCV图像增强:模糊图片成过去,高清蜕变有何妙招?
C++OpenCV手指调音量:传统操作已 out,新解法如何脱颖而出?
C++OpenCV手指检测:为何开发者纷纷放弃传统,拥抱高效新解法
以上就是我的分享。这些分析皆源自我的个人经验,希望上面分享的这些东西对大家有帮助,感谢大家!
文章中源代码怎么获取:关注官方微信公众号,就可以获取。
原文作者:讳疾忌医-note;如有侵权,请联系管理员删除。