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++工程师#
全部评论

相关推荐

点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务