return语句终止当前正在执行的函数,并将控制权返回到调用该函数的地方
return;//没有返回值的一般用在返回值类型void的函数中,可以不写,这种函数会隐式的执行return
return 表达式;//返回函数的结果,除开void函数,其他返回值类型函数都必须返回一个值,并且return的返回值类型必须与函数返回值类型相同,或者能够隐式的转换为相同的类型
void swap(int& a, int& b) {
if (a == b) {
return;//如果a=b那么直接退出函数,类似与if,for,while里的break
}
int temp = a;
a = b;
b = temp;
//此处无需显示的return,编译器会隐式的执行
//在返回值类型void的函数中也可以 用return 表达式;语句,但是这个表达式的最终计算结果一定要为空。
}
//这是一段错误的代码
bool str_subrange(const string& str1, const string& str2) {
if (str1.size() == str2.size()) {
return str1 == str2;// == 返回布尔值
}
auto size = (str1.size() < str2.size())//检查两个字符串那个短,用size接收较小的字符串
? str1.size() : str2.size();
for (decltype(size) i = 0; i != size; ++i) {
if (str1[i] != str2[i])//判断两个字符串到size长度的每个字符是否不相同
return ;//错误1,此处错误没有返回值,要想编译通过则需要返回布尔值0或1,true或false
}
//错误2,控制流未返回值就结束了函数
//编译器可能检查不出这样的错误,如果编译器未发现这样的错误,那么运行时这个函数将会处理成未定义的函数
}
在有return语句的循环后面也应该跟一条return语句,如果没有该程序就是错误的。很多编译器都发现不了这样的错误
**
值是如何被返回的
**
string make_plural(size_t ctr, const string& word, const string& ending) {
return (ctr > 1) ? word + ending : word;
}
该函数的返回类型是string,意味着返回值将被拷贝到调用点,因此该函数将返回word的副本或者一个未命名的临时的string对象
//调用 make_plural
int main()
{
string str;
make_plural(2, "do", "ing");//这是返回的一个未命名的临时的string对象
str = make_plural(2, "go", "ing");//这是将函数的结果拷贝给str
cout << str << endl;
system("pause");
return 0;
}
同其他引用类型一样,如果函数返回引用,则该引用仅是它所引用对象的别名
const string& shorterString(const string& s1, const string& s2) {
return s1.size() <= s2.size() ? s1 : s2;
}
int main()
{
string a = "good", b = "bad",c;
c = shorterString(a, b);
/*此处shorterString对应引用是c,s1是a的别名,s2是b的别名,所以不会产生任何拷贝*/
cout << c << endl;
cout<<shorterString("hello", "C++")<<endl;//这里所引用的都是未命名的临时的string对象
system("pause");
return 0;
}
不要返回局部对象的引用或指针
const string& manip() {
string ret;
if (!ret.empty()) {
return ret;//错误:返回局部对象的引用
}
else {
return "Empty";//错误Empty是一个局部的临时量
}
}
返回局部对象的引用是错误的,同样返回局部对象的指针也是错误的。
一旦函数完成,局部对象被释放,指针将指向一个不存在的对象
//但是如果只是值传递的函数,那么该函数会产生拷贝该函数就是正确的
string manip() {
string ret;
if (!ret.empty()) {
return ret;
}
else {
return "Empty";
}
}
列表初始化返回值
vector<string>process(string expected,string actual) {
if (expected.empty()) {
return {};
}
else if (expected == actual) {
return { "functionX","okay" };
}
else {
return { "functionX",expected,actual };
}
}
int main()
{
vector<string>a;
a = process("hello", "world");//用a来接收返回列表的结果
for (auto i : a) {
cout << i;
}
system("pause");
return 0;
}
主函数main的返回值
main函数的返回值可以看作是状态指示器,返回0则代表执行成功其他代表失败,cstdlib头文件定义了两个预处理变量,可以分别用这两个变量表示成功和失败
return EXIT_FAILURE;//失败
return EXIT_SUCCESS;//成功
递归
如果一个函数调用它自身,不管该函数是直接的还是间接的,都称该函数为递归函数
main函数不能调用它自身
练习6.30
编译器报错,提示函数必须有返回值
练习6.31
返回的引用无效:局部临时变量或者局部对象的引用对于返回都是无效的,因为在函数终止之后,局部变量或者对象的引用不再指向有效的内存区域。若是常量在函数调用之前存在,引用即可用。
练习6.31
合法,返回的是数组第1~10个元素
练习6.32
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
using Iter = vector<int>::iterator;
void print(Iter beg, Iter end)
{
if (beg != end) {
cout << *beg << " ";
print(++beg, end);
}else
{
cout << endl;
return;
}
}
int main()
{
vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};
print(vec.begin(), vec.end());
return 0;
}
练习6.33
当递归终止条件变成var != 0时,可能会出现两种情况:
情况1:如果参数为正,递归在0处停止。
情况2:如果参数是负的,递归就不会停止,函数将会不断地调用它自身直到程序栈空间耗尽为止。
练习6.34
al–会把val减1再返回val的初始值,递归函数会一直使用val作为参数,使程序陷入无限循环。