【和春笋一起学C++】(五十二)关于函数返回对象时的注意事项

目录

[1. 返回对象](#1. 返回对象)

[2. 返回指向对象的引用](#2. 返回指向对象的引用)

[3. 返回const对象](#3. 返回const对象)

[4. 返回指向对象的const引用](#4. 返回指向对象的const引用)

[5. 总结](#5. 总结)


函数返回对象有以下几种方式:

  1. 返回对象;
  2. 返回指向对象的引用;
  3. 返回const对象;
  4. 返回指向对象的const引用;

1. 返回对象

函数返回对象需要调用复制构造函数,而返回对象的引用则不需要,显然,返回对象的引用执行效率更高。但如果被返回的对象是调用函数中的局部变量,则不能按引用方式返回它,因为调用函数执行完毕时,局部对象将调用其析构函数。因此,当控制权回到调用函数时,引用指向的对象将不再存在。在这种情况下,应返回对象,而不是引用。如下面的strcat函数,只能返回string对象,不能返回string对象引用。

cpp 复制代码
std::string strcat(std::string& s1, std::string& s2)
{
	std::string s3 = s1 + s2;
	return s3;
}

int main()
{
	string s1 = "abc";
	string s2 = "efg";
	string s3 = strcat(s1, s2);
	cout << "s3=" << s3 << endl;
    return 0;
}

如果把strcat函数的返回改成string对象的引用,则运行将报错,因为strcat函数中的s3是局部变量,在strcat函数运行结束后s3对象将不再存在。但如果返回的是string对象,就不会出现这种问题,s3会通过复制构造函数创建一个临时对象,并将s3的内容拷贝至该临时对象,调用函数通过访问临时对象获取具体的数据内容。

2. 返回指向对象的引用

如《C++中string类简介》文章中的重载赋值操作符函数,定义如下:

cpp 复制代码
MyClassString& MyClassString::operator=(const MyClassString& s)
{
	if (this == &s)
	{
		return *this;
	}
	delete[]str;
	len = s.len;
	str = new char[len + 1];
	strcpy(str,s.str);
	return *this;
}

函数参数为指向MyClassString对象的const引用,返回指向MyClassString对象的引用。函数返回传递给它的对象的引用,这种方式在操作符重载函数中很常见。MyClassString类的输出操作符重载函数也返回了传递给它的对象的引用,如下:

cpp 复制代码
friend std::ostream& operator<< (std::ostream& os, const MyClassString& st)
{
	os << st.str;
	return os;
}

函数返回对象的引用可以提高函数的运行效率,但使用对象的引用作为函数返回时有一些限制条件,即返回不能是局部对象。

3. 返回const对象

返回const对象可以防止返回值被随意篡改,如上面的strcat函数,将返回值改成const,如下:

cpp 复制代码
const std::string strcat(std::string& s1, std::string& s2)
{
	std::string s3 = s1 + s2;
	return s3;
}

此时,下面的代码成立:

cpp 复制代码
int main()
{
	string s1 = "abc";
	string s2 = "efg";
	string s3 = strcat(s1, s2);
	cout << "s3=" << s3 << endl;
    return 0;
}

但如下的代码不成立,不能编译通过。

cpp 复制代码
int main()
{
	string s1 = "abc";
	string s2 = "efg";
	string s3 = "xyz";
	strcat(s1, s2) = s3;
    return 0;
}

因为const对象是不能被赋值的。

4. 返回指向对象的const引用

返回指向对象的const引用可以提高程序的执行效率,如将上述strcat函数改成指向string对象的const引用,如下:

cpp 复制代码
const std::string& strcat(std::string& s1, std::string& s2)
{
	s1 = s1 + s2;
	return s1;
}

5. 总结

  1. 如果方法或函数要返回局部对象,则应返回对象,而不是指向对象的引用。在这种情况下,将使用复制构造函数来生成返回的对象。
  2. 如果方法或函数要返回一个没有公有复制构造函数的类(如ostream类)的对象,则它必须返回一个指向该类对象的引用。
  3. 如果方法或函数可以返回对象,也可以返回指向对象的引用,这种情况下,应优先选择返回对象的引用,因为其执行效率更高。
相关推荐
Methy2 分钟前
IoTHub半个月崩了五次?都是裸rethrow惹的祸
服务器·c++·后端
我不会起名字32211 分钟前
一天一道力扣Hot100(36):深度优先算法---组合总和
数据结构·c++·后端·python·算法·go
纪念 22916 分钟前
c++类和对象(四)
开发语言·c++
汉克老师27 分钟前
GESP2026年9月认证C++六级( 第三部分编程题(2、分树规划))精讲
c++·gesp·小学生·学c++编程
学生小羊34 分钟前
C++ 初阶 学习博客
c语言·c++·c++与c语言的区别·c++基础学习
辛苦才能1 小时前
C++多态原理:虚函数表的内存布局与动态绑定的汇编真相
开发语言·c++
西西弗Sisyphus1 小时前
Qt 实现一个 水波进度球
c++·qt·c
无忧.芙桃1 小时前
数据结构之排序算法(中):冒泡排序与快速排序,从相邻交换到工程级优化
c语言·c++·排序算法
Hhy_11071 小时前
《C++深度解构04》类和对象(下)——类型转换、static、友元与编译器优化
c语言·c++·学习·类和对象·visual studio
qq_199886872 小时前
第7板块·第1节:通用算子分类与设计模式
c++·人工智能·gpu算力·cuda