C/C++函数如何返回多个值?有哪些常用实现方式

来源:站长源码作者:北京GEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C/C++函数如何返回多个值?有哪些常用实现方式》,敬请观看详情。想从C或C++函数里一次拿回好几个计算结果,直接写return却只能给出一个值,这种限制常让人卡在接口设计上。其实底层做法很清晰:C语言常用结构体打包字段,或用指针形参让函数把结果写回调用处;C++在此基础上还能用std::pair、std::tuple以及引用参数。不同方案在可读性和拷贝开销上有明显区别,比如结构体适合固定字段的业务对象,tuple适合临时聚合,引用参数则避免多余拷贝。弄清这些机制后,就能按场景选最顺手的办法,不再为多返回值绕弯子。

在C和C++开发中,标准函数的return语句一次只能把一个对象交给调用者。但实际业务里经常需要同时拿到状态码、计算结果、长度信息等多个数据。要解决这个问题,并不是语言做不到,而是需要换一种数据传递思路。下面介绍几种在工程中稳定可用的做法,并给出可运行的代码示例。

C/C++函数如何返回多个值?有哪些常用实现方式

使用结构体或类打包返回

最直观的方式是定义一个结构体,把要返回的多个字段都放进去,函数返回这个结构体实例。这样做语义清晰,调用方通过成员名取值,不易混淆顺序。

在C语言中,结构体是聚合数据的基本手段。下面例子用一个Result结构体同时携带商和余数:

#include <stdio.h>

typedef struct {
    int quotient;
    int remainder;
} DivResult;

DivResult divide(int a, int b) {
    DivResult r;
    r.quotient = a / b;
    r.remainder = a % b;
    return r;
}

int main() {
    DivResult res = divide(17, 5);
    printf("quotient=%d, remainder=%dn", res.quotient, res.remainder);
    return 0;
}

C++中可以进一步用class并加上构造函数,或者使用std::tuple等模板类型。结构体的优点是类型稳定、字段命名明确,编译器也容易做返回值优化,避免不必要的拷贝。缺点是如果只偶尔返回两个临时值,定义新类型显得稍重。

通过指针或引用参数写回结果

另一种常见思路是函数本身返回状态码或主结果,其余数据通过指针(C)或引用(C++)形参传出来。函数内部给这些参数指向的变量赋值,调用方事先准备好变量地址。

C语言风格示例:

#include <stdio.h>

int divide(int a, int b, int* quotient, int* remainder) {
    if (b == 0) return -1;
    *quotient = a / b;
    *remainder = a % b;
    return 0;
}

int main() {
    int q, r, ret;
    ret = divide(17, 5, &q, &r);
    if (ret == 0) {
        printf("quotient=%d, remainder=%dn", q, r);
    }
    return 0;
}

C++推荐使用引用而非指针,能减少空指针风险,调用语法也更干净:

#include <iostream>

bool divide(int a, int b, int& quotient, int& remainder) {
    if (b == 0) return false;
    quotient = a / b;
    remainder = a % b;
    return true;
}

int main() {
    int q, r;
    if (divide(17, 5, q, r)) {
        std::cout << "quotient=" << q << ", remainder=" << r << std::endl;
    }
    return 0;
}

这种方式的优势是无需构造聚合对象,特别适合已有变量直接接收结果的场景。问题在于接口不如返回值聚合那样自解释,调用时容易忘记传地址或传错变量。

C++专用:std::pair与std::tuple

如果返回的两个或三个值没有长期存在的业务含义,只是函数内部临时凑一组,C++标准库提供了pair和tuple。pair固定两个元素,tuple可容纳任意数量。

使用std::tuple的例子:

#include <iostream>
#include <tuple>

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

int main() {
    auto res = divide(17, 5);
    std::cout << "quotient=" << std::get<0>(res)
              << ", remainder=" << std::get<1>(res) << std::endl;
    return 0;
}

从C++17起还能用结构化绑定,让代码更接近多返回值语言的体验:

#include <iostream>
#include <tuple>

std::tuple<int, int> divide(int a, int b) {
    return {a / b, a % b};
}

int main() {
    auto [q, r] = divide(17, 5);
    std::cout << "quotient=" << q << ", remainder=" << r << std::endl;
    return 0;
}

pair和tuple轻量、无需预定义类型,在标准算法和临时计算中很方便。但元素通过位置访问,代码可读性弱于命名结构体,字段一多就容易记错顺序。

不同方案的选择建议

面对具体需求时,可参考下面的对照表快速决定:

场景推荐方式理由
返回固定业务对象多个属性结构体/类字段命名清晰,易维护
C语言遗留接口指针参数无额外类型依赖
C++需避免拷贝且要状态返回引用参数安全且语法简洁
临时聚合两三个值pair/tuple无需新类型,灵活

总体原则是把返回内容是否具备独立业务含义作为第一判断条件。有含义就打包成类型,无含义且数量少就用标准库容器。这样既能保证代码清楚,也能让后续维护者一眼看懂数据流向。

C++返回多个值结构体修改时间:2026-08-04 22:33:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。