函数的返回值

无返回值的函数

没有返回值的return语句只能用于返回类型是void的函数中。返回void的函数可以没有return语句,这类函数的最后一句后面会隐式地执行return。而如果void函数需要在函数中间退出,可以使用return语句。例如一个值交换的函数:

void swap(int &v1, int &v2) {
    if(v1 == v2)
        return;
    // 程序中间退出
    int temp = v2;
    v2 = v1;
    v1 = temp;
    // 无显式return语句
}

有返回值的函数

只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值。且return语句的类型必须与函数的返回类型相同,或者能够隐式转换成函数的类型。

值是如何返回的

返回一个值的方式和初始化变量或形参的方式一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。

分别举一个返回值和返回引用的例子:

// 如果ctr的值大于1则返货复数形式,否则返回原型
string makePlural(size_t ctr, const string &word, const string &ending) {
    return (ctr > 1) ? word + ending : word;
}

该函数的返回类型是string,意味着返回值将被拷贝到调用点。因此,该函数将返回一个未命名的临时string对象或者一个word的副本。

如果函数返回引用,则该引用只是它所引对象的一个别名。

// 返回两个string对象中较短的那个
const string &shorterString(const string &s1, const string &s2) {
    return s1.size() <= s2.size() ? s1 : s2;
}

这个函数的形参和返回类型都是const string的引用,所以不管是调用函数还是返回结果都不会拷贝string对象。

不要返回局部对象的引用或指针

函数结束后,其所占用的存储空间也随之被释放,因此,函数终止意味着其中的局部变量的引用将指向无效的内存区域:

const string& manip() {
    string ret;
    if(!ret.empty())
        return ret;        // 错误:返回的是局部对象的引用
    else
        return "Empty";    // 错误:"Empty"是一个局部临时量
}

上面两条return语句都将返回未定义的值,也就是说,试图使用manip函数的返回值将发生未定义的行为。

返回类类型的函数和调用运算符

如果函数返回指针、引用或类的对象,我们就能使用函数调用的结果访问结果对象的成员。例如:

    // 调用string对象的size成员
    auto sz = shorterString(s1, s2).size();

引用返回左值

调用一个返回引用的函数得到左值,其他返回类型得到右值。特别地,我们能够为返回类型是非常量引用的函数的结果赋值:

char &getVal(string &str, string::size_type ix) {
    return str[ix];
}
int main() {
    string s("a value");
    cout << s << endl;
    getVal(s, 0) = 'A';    // 将A[0]的值改为A
    cout << s << endl;
    
    return 0;
}

返回值是一个引用,因此调用的是左值,和其他左值一样它也可以出现在赋值运算符的左侧。

而如果返回类型是常量引用,则不能对调用的结果赋值,例如之前的shorterString函数:

    shorterString("hi", "bye") = "X";    // 错误:返回值是常量引用

列表初始化返回值

C++11新标准规定,函数可以返回花括号包围的值的列表,此列表也用来对表示函数返回的临时量进行初始化。如果列表为空,临时量执行值初始化;否则,返回值由函数的返回类型决定。例如:

vector<string> process(const srting &expected) {
    if(expected.empty())
        return {};
    else
        return {"okay", "function"};
}

如果函数返回的是内置类型,则花括号包围的列表最多包含一个值,并且该值所占的空间不能大于目标类型的空间。如果函数返回的是类类型,由类本身定义初始值如何使用。

posted @ 2020-03-20 02:43  southernEast  阅读(501)  评论(0编辑  收藏  举报