modern c++的写法思考之多值返回

传统写c++函数的方式为,入参和出参都在一块,出参通常为引用,所以能看出来哪些是出参,而返回值通常为int,为0表示正常,为负数表示出错。然后每个函数调用之后,都需要使用if做一把判断。这当然也是一种行之有效的办法,而且简单好遵守,在各种大型项目都有使用。

现代的c++函数写法,可以不用通过引用接收多个返回值了,而由函数直接返回多个不同类型的值,就像python动态语言那样爽。尽管在性能和易于理解方面我持保留态度,不过,既然现代c++的设计标准里提供了,便学一学,多学无害。

以往如果是正好要返回两个值,那可以使用std::pair也就足够,如:

pair<string, int> get_name_and_height() {
    return make_pair("zhang san", 180);
}

新的tuple便能支持多值返回,当然也包括两值,如:

tuple<int, float, string> run() {
    return make_tuple(1, 3.14f, "haha");
}
int main()
{
    int num;
    float pi;
    string name;
    tie(num, pi, name) = run();
    return 0;
}

这种写法跟PHP里的list()写法很像,还是有些繁琐,据说最新版本的c++编译器(>=c++17)已经支持类似Python的写法了:

auto [num, pi, name] = run();

其实就是如何去解绑tuple数据,最新的写法有点太pythonic了,简直不像C++。

实际工程实践中,会有返回值增加的时候,如果某个函数返回的值要多一个,就得把所有调用的位置都修改一遍也是很心累的,所以也可以按位置手动去取结果:

auto ret = run();
cout << std::get<0>(ret) << std::get<1>(ret) << std::get<2>(ret) << endl;

这个解决了兼容问题,但是却解决不了难以理解的问题,时间久了,鬼才知道位置1处是代表啥意思。

除了tuple,更推荐的是使用临时结构体来返回,兼容性好,也易读:

auto run2() {
    struct Ret {
        int n;
        float pi;
        string name;
    };
    return Ret{1, 3.14f, "haha"};
}
int main()
{
    auto ret2 = run2();
    cout << typeid(ret2).name() << " " << ret2.n << ret2.pi << ret2.name << endl;
}

有人可能又会说了,既然是临时结构体,我压根就不关心它叫什么,我只关心它有哪些字段,所以连定义这个结构体都是很麻烦的事,那么就可以简写成如下形式:

auto run2() {
    return (struct{ int n; float pi; string name; }){1, 3.14f, "haha"};
}
int main()
{
    auto ret2 = run2();
    cout << typeid(ret2).name() << " " << ret2.n << ret2.pi << ret2.name << endl;
}

回到最初,如果没有返回值来确定状态,如何知道返回的结果是否可用呢?我也在琢磨这个问题,感觉现在的c++写法从设计上更推崇使用try...catch()来处理不正常状态,原来那种一堆对返回值的if判断的写法,也确实恶心,不过它又管用。

发表于 2018年10月11日 21:08   评论:1   阅读:2797  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo