return 语句

return 语句用于结束当前正在执行的函数,并将控制权返回给调用此函数的函数。return 语句有两种形式:

return;
return expression;

没有返回值的函数

不带返回值的 return 语句只能用于返回类型为 void 的函数。在返回类型为 void 的函数中,return 返回语句不是必需的,隐式的 return 发生在函数的最后一个语句完成时。

一般情况下,返回类型是 void 的函数使用 return 语句是为了引起函数的强制结束,这种 return 的用法类似于循环结构中的 break 语句的作用。例如,可如下重写 swap 程序,使之在输入的两个数值相同时不执行任何工作:

// ok: swap acts on references to its arguments
void swap(int &v1, int &v2)
{
// if values already the same, no need to swap, just return if (v1 == v2) return; // ok, have work to do int tmp = v2; v2 = v1; v1 = tmp; // no explicit return necessary }

返回类型为 void 的函数通常不能使用第二种形式的 return 语句,但是,它可以返回另一个返回类型同样是 void 的函数的调用结果:

void do_swap(int &v1, int &v2)
{
int tmp = v2;
v2 = v1;
v1 = tmp;
// ok: void function doesn't need an explicit return
}

void swap(int &v1, int &v2)
{
if (v1 == v2)
return false; // error: void function cannot return a value
return do_swap(v1, v2); // ok: returns call to a void function
}

返回任何其他表达式的尝试都会导致编译时的错误。         

具有返回值的函数

return 语句的第二种形式提供了函数的结果。任何返回类型不是 void 的函数必须返回一个值,而且这个返回值的类型必须和函数的返回类型相同,或者能隐式转化为函数的返回类型。

尽管 C++ 不能确保结果的正确性,但能保证函数每一次 return 都返回适当类型的结果。

主函数 main 的返回值

返回类型不是 void 的函数必须返回一个值,但此规则有一个例外情况:允许主函数 main 没有返回值就可结束。如果程序控制执行到主函数 main 的最后一个语句都还没有返回,那么编译器会隐式地插入返回 0 的语句。

可将主函数 main 返回的值视为状态指示器。返回 0 表示程序运行成功,其他大部分返回值则表示失败。非 0 返回值的意义因机器不同而不同,为了使返回值独立于机器,cstdlib 头文件定义了两个预处理变量,分别用于表示程序运行成功和失败:#include <cstdlib>

int main()
{
if (some_failure)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}

代码不再需要使用那些依赖于机器的精确返回值。相应地,这些值都在 cstdlib 库中定义,我们的代码不需要做任何修改。

返回非引用类型

函数的返回值用于初始化在调用函数处创建的临时对象。在求解表达式时,如果需要一个地方储存其运算结果,编译器会创建一个没有命名的对象,这就是临时对象。

用函数返回值初始化临时对象与用实参初始化形参的方法是一样的。如果返回类型不是引用,在调用函数的地方会将函数返回值复制给临时对象。当函数返回非引用类型时,其返回值既可以是局部对象,也可以是求解表达式的结果。

// return plural version of word if ctr isn't 1
string make_plural(size_t ctr, const string &word,
const string &ending)
{
return (ctr == 1) ? word : word + ending;
}

我们可以使用这样的函数来输出单词的单数或复数形式。这个函数要么返回其形参 word 的副本,要么返回一个未命名的临时string 对象,这个临时对象是由字符串 word 和 ending 的相加而产生的。这两种情况下,return 都在调用该函数的地方复制了返回的 string 对象。

返回引用

当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。例如,考虑下面的函数,此函数返回两个 string 类型形参中较短的那个字符串的引用:

// find longer of two strings
const string &shorterString(const string &s1, const string &s2)
{
return s1.size() < s2.size() ? s1 : s2;
}

形参和返回类型都是指向 const string 对象的引用,调用函数和返回结果时,都没有复制这些 string 对象。

不要返回局部对象的引用

当函数执行完毕时,将释放分配给局部对象的存储空间。此时,对局部对象的引用就会指向不确定的内存。考虑下面的程序:

// Disaster: Function returns a reference to a local object
const string &manip(const string& s)
{
string ret = s;
// transform ret in some way
return ret; // Wrong: Returning reference to a local object!
}

这个函数会在运行时出错, 因为它返回了局部对象的引用。 当函数执行完毕,字符串 ret 占用的储存空间被释放,函数返回值指向了对于这个程序来说不再有效的内存空间。

引用返回左值

返回引用的函数返回一个左值。因此,这样的函数可用于任何要求使用左值的地方:

char &get_val(string &str, string::size_type ix)
{
return str[ix];
}

int main()
{
string s("a value");
cout << s << endl; // prints a value
get_val(s, 0) = 'A'; // changes s[0] to A
cout << s << endl; // prints A value
return 0;
}

给函数返回值赋值可能让人惊讶,由于函数返回的是一个引用,因此这是正

确的,该引用是被返回元素的同义词。

如果不希望引用返回值被修改,返回值应该声明为 const:

const char &get_val(...

不要返回指向局部对象的指针

函数的返回类型可以是大多数类型。特别地,函数也可以返回指针类型。和返回局部对象的引用一样, 返回指向局部对象的指针也是错误的。一旦函数结束,局部对象被释放, 返回的指针就变成了指向不再存在的对象的悬垂指针。

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

调用运算符也有优先级和结合律,调用运算符的优先级与点运算符和箭头运算符相同,并且也符合左结合律。因此,如果函数返回指针、引用或类的对象。我们就能使用函数调用的结果访问结果对象的成员。

auto sz=shorterString(s1,s2).size();

因为上面提到的运算符都满足左结合律,所以shorterString的结果是点运算符的左侧运算对象,点运算符可以得到该string对对象的size成员,size又是第二个调用的运算符的左侧运算对象。

列表初始化返回值

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

vector<string> process()
{
if(expected.empty())
return {};
else if(expected==actual)
return{“functionX”,“okay”};
else
return {“functionX”,expected,actual};
}

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

递归

直接或间接调用自己的函数称为递归函数。一个简单的递归函数例子是阶乘的计算。数 n 阶乘是从 1 到 n 的乘积。例如,5 的阶乘就是 120。

1 * 2 * 3 * 4 * 5 = 120

解决这个问题的自然方法就是递归:

// calculate val!, which is 1*2 *3 ... * val
int factorial(int val)
{
if (val > 1)
return factorial(val-1) * val;
return 1;
}

递归函数必须定义一个终止条件;否则,函数就会“永远”递归下去,这意味着函数会一直调用自身直到程序栈耗尽。有时候,这种现象称为“无限递归错误”。对于函数 factorial,val 为 1 是终止条件。

主函数 main 不能调用自身。

转载于:https://www.cnblogs.com/xiaojianliu/articles/8979419.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值