C++ Primer第六章③

C++ Primer

第六章 函数

返回类型和return语句

return语句终止当前正在执行的函数,并把控制权返回到调用该函数的地方。

无返回值的函数

就是我们之前写的返回类型为void的函数:

void f()
{
    return; //也可以不写
}

有返回值的函数

只要函数的返回类型不是void,那必须要有return内容。我的经验是,要保证任何情况都有返回。因为实际项目中的代码逻辑都比较复杂,一定注意不要有没有返回值得情况,这个得程序员自己注意,因为编译器基本检查不出这种类型的错误:

int f() //这种函数编译器不会报错的
{

}
值是如何被返回的
  1. 返回类型为值: 其实和初始化一个变量的方式完全一样,返回的值会初始化一个临时的对象,然后赋值给调用点。
    string plus(const string &word, const string &p)
    {
     return word + p;
    }
    
    该函数的返回类型是string,值类型,也就是说,返回值会被拷贝到调用点,这个函数在返回的时候会创建一个临时的string对象(内容是word+p),然后给调用点。 这样是不是很麻烦且浪费呢?我们当然可以不拷贝,怎么办呢,用引用啊
  2. 返回类型为引用:
    //返回两个string中较短的那个
    const string &shortStr(const string &s1, const string &s2)
    {
     return s1.size() <= s2.size() ? s1 : s2;
    }
    
graph LR
形参为引用-->调用函数时不用拷贝string对象
graph LR
返回类型为引用-->返回结果不用拷贝string对象

那么,是不是这么好用呢?你如果很注意细节的话当然是,但这个稍不注意就会出错,不信你看看下面的这个函数对不对:

//判断string是不是空的
const string &f()
{
    string ret;
    if(!ret.empty())
    {
        return ret;
    }
    else
    {
        return "empty";
    }
}

两处返回值都错了,返回ret肯定错,因为ret是在被调用函数中定义的,当return之后ret都被销毁了,怎么还能返回引用呢?那之前的怎么合法呢?因为人家不是自己定义啊,是主调函数传进来的。第二个也是同样的错误,"empty"只是个在被调函数中临时创建的对象,return之后也是要销毁的。 调用一个返回引用的函数得到左值(身份),其他返回类型得到右值(内容),所以啊,我们可以像使用其他左值那样来使用返回引用的函数的调用,比如,可以给返回类型是非常量引用的函数的结果赋值:

int &getVal(){}
int main()
{
    getVal() = 5; //这样是合法的
    return 0;
}
列表初始化返回值:只不过是返回的数据类型复杂些:
vector<string> process()
{
    if(1)
    {
        return {}; //返回空vector对象
    }
    else
    {
        return {"你看不到我"};
    }
}
看看老伙计main函数
int main()
{

}

这样写会报错吗?它没有return语句啊,没事,编译器会隐式插入一条return 0; 返回0表示执行成功,返回其他值表示执行失败,具体含义依机器而定。

递归

我认为递归是最考验你对函数调用理解的,我们来写个递归求阶乘的:

int fact(int val)
{
    if(val > 1)
    {
        return fact(val-1) * val;
    }
    return 1; //一定要有这个触底反弹
}

你可以试试按照上面的函数求个5的阶乘,有助于理解哦。

返回数组指针

因为数组不能被拷贝,所以函数不能返回数组,只能返回数组的指针或者引用。

int (*f())[10]; //函数返回的是指针,指向一个大小为10的int数组

因为这样看起来比较麻烦,我们可以用之前学过的类型别名:

using arr = int[10];
arr* f(); //这样的声明就比较简洁了

除了使用类型别名外,C++还有一种方法:尾置返回类型,顾名思义,就是把返回类型放后面:

auto f() -> int(*)[10]

别忘了我们还有一个神器,decltype:

int a[] = {1,2,3};
decltype(a) *arrp(){} //返回类型是指针,且指向的类型与a一致
//使用它的前提是我们知道返回的指针指向什么类型的数组。
#C++工程师#
全部评论

相关推荐

05-12 10:10
已编辑
门头沟学院 人工智能
写这篇之前我犹豫了挺久。一方面是怕被人骂,&quot;又一个收割焦虑的转行帖&quot;;另一方面是看了太多用&nbsp;GPT&nbsp;套娃出来的「学习路线」文章,AI&nbsp;味重得让人没法读完。所以这篇全是亲身踩过的坑,时间线、用过的项目、当时的心路全都尽量原样写出来。如果你是大学生在迷茫要不要转&nbsp;AI,或者已经在转的路上,希望能给点参考。&nbsp;一个反共识的开场:你以为进&nbsp;OpenAI&nbsp;的人都是博士?&nbsp;先讲个故事,跟我没关系,但跟所有想转&nbsp;AI&nbsp;的人都有关系。&nbsp;OpenAI&nbsp;的&nbsp;Sora&nbsp;团队(就是搞文生视频那个)一共&nbsp;13&nbsp;个人。这里面有两个人特别有意思:&nbsp;Will&nbsp;DePue,密歇根大学计算机系,直接辍学了。17...
_hengheng:我也本,也算是做ai相关,我最开始感觉做ai工程师有多么多么困难,后来发现懂了原理后整体训练完全可以看成一个流程化的内容,开源方案太多了,大多基本都是按着模子在自家业务上做各种操作,就算是大厂的小部门也没那么多资源去训基模,反而更多的是像怎么把技术往业务方向靠近了,不过当前时代如果本科学历没那么好加上自己执行力不是特别强还真不建议走ai工程师这条路,可以试试其他ai的偏业务方向,不然校招不太好杀出来
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务