C++ primer 6.3返回类型和return语句 && 6.3.1无返回值函数 &&6.3.2有返回值参数

本文探讨C++中函数返回值的处理,包括值拷贝、引用安全、列表初始化返回值以及递归函数的使用。强调了不要返回局部对象的引用或指针,因为它们在函数结束时会被释放。同时,介绍了main函数的返回状态以及递归函数的潜在风险,如无限递归可能导致栈溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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作为参数,使程序陷入无限循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值