值返回与引用返回(c++)

目录

值返回

引用返回

二者的区别

生命周期

可以安全引用返回的情况

返回函数参数(传入的引用)

返回成员变量

返回动态分配的对象(但通常是返回指针)

禁止返回的类型

返回局部变量

返回临时对象

返回局部指针指向的对象

复制代码试一下

总结


在c++中函数可以返回值(by value)也可以返回引用(by reference)。

两者的根本区别在于返回的是对象的副本还是对象本身

值返回

返回对象的副本 ,调用者得到的是全新的独立对象

cpp 复制代码
// 值返回:返回类型不带&
string function1() {        // 返回string(值)
    string local = "hello would";
    return local;          // 返回local的副本
}

引用返回

返回对象的引用(别名) ,调用者得到的是已有对象的另一个名称,不创建新对象。

cpp 复制代码
// 引用返回:返回类型带&
string& function2() {       // 返回string&(引用)
    static string global = "world";
    return global;         // 返回global的引用(别名)
}

// const引用返回
const string& function3() { // 返回const string&(常量引用)
    static string global = "world";
    return global;         // 返回不能修改的引用
}

二者的区别

最主要的判断方式是其函数类型后是否跟着& 若其跟着&即为返回对象的引用 不创建新的对象

生命周期

值返回例子如下

cpp 复制代码
string version1(const string& s1, const string& s2)
{
	string temp;//创建局部变量temp(在栈上)
	temp = s2 + s1 + s2;//计算s2+s1+s2,赋值给temp
	return temp;//创建temp的副本(临时对象)作为返回值
}
//函数结束:temp被销毁(栈帧弹出)
//主函数中:用返回值初始化或赋值给result(调用拷贝构造函数或赋值运算符)

即可以得出version1返回的是值 并且在返回后temp被销毁 而其return的是temp的副本与temp本身的销毁无关 完全的独立

引用返回

version3 当函数结束后,temp就被销毁了,所以返回的引用将指向一个不再存在的对象,这会导致未定义行为。注意:不要返回局部变量的引用或指针

可以安全引用返回的情况

返回静态局部变量

cpp 复制代码
const string& getDefaultName() {
    static string defaultName = "Default";  // 静态变量 
    return defaultName;  // 安全:生命周期为整个程序不会随着函数结束而销毁
}

返回函数参数(传入的引用)

cpp 复制代码
​
string& appendStars(string& str) {
    str += "***";
    return str;  // 安全:str的生命周期由调用者管理
}

返回成员变量

cpp 复制代码
class Person {
private:
    string name;
public:
    const string& getName() const { return name; }  // 安全
    string& getName() { return name; }              // 安全(但有风险)
};

返回动态分配的对象(但通常是返回指针)

cpp 复制代码
string* createDynamicString() {
    return new string("Dynamic");  // 返回指针,调用者需delete
}

禁止返回的类型

返回局部变量

cpp 复制代码
const string& badFunction() {
    string local = "Local";  // 局部变量
    return local;  // 致命错误!返回后将指向无效内存
}

返回临时对象

cpp 复制代码
const string& badFunction2() {
    return string("Temporary");  // 临时对象,语句结束就销毁
}

返回局部指针指向的对象

cpp 复制代码
string& badFunction3() {
    string* ptr = new string("Dynamic");
    return *ptr;  // 危险:内存泄漏风险,调用者不知道需要delete
}

总结 注意:不要返回局部变量的引用或指针

复制代码试一下

cpp 复制代码
//strquote.cpp -- different designs
#include<iostream>
#include<string>
using namespace std;
string version1(const string& s1, const string& s2);
const string& version2(string& s1, const string& s2);	//has side effect
const string& version3(string& s1, const string& s2);	//bad design
 
int main()
{
	string input;
	string copy;
	string result;
 
	cout << "Enter a string: ";
	getline(cin, input);
	copy = input;
	cout << "Your string as entered: " << input << endl;
	result = version1(input, "***");
	cout << "Your string enhanced: " << result << endl;
	cout << "Your original string: " << input << endl;
 
	result = version2(input, "###");
	cout << "Your string enhanced: " << result << endl;
	cout << "Your original string: " << input << endl;
 
	cout << "Resetting original string.\n";
	input = copy;
	result = version3(input, "@@@");
	cout << "Your string enhanced: " << result << endl;
	cout << "Your original string: " << input << endl;
	return 0;
}
 
string version1(const string& s1, const string& s2)
{
	string temp;
	temp = s2 + s1 + s2;
	return temp;
}
 
const string& version2(string& s1, const string& s2)	//has side effect
{
	s1 = s2 + s1 + s2;
//safe to return reference passed to function
	return s1;
}
 
const string& version3(string& s1, const string& s2)	//bad design
{
	string temp;
	temp = s2 + s1 + s2;
//unsafe to return reference to local variable
	return temp;
}

此代码可以帮助你观察与理解值返回与引用返回的区别

总结

场景 值返回 引用返回
返回计算结果 ✅ 推荐 ⚠️ 需确保对象有效
返回局部创建的对象 ✅ 安全 ❌ 绝对禁止
返回输入参数 ⚠️ 可能低效 ✅ 高效
返回静态数据 ⚠️ 可能拷贝 ✅ 高效
链式调用 ❌ 不能链式 ✅ 支持链式
函数修改参数 ❌ 不能修改 ✅ 可以修改
多线程安全 ✅ 线程安全 ⚠️ 需同步访问
相关推荐
leo__52021 小时前
基于菲涅耳衍射积分的空心高斯光束传输数值模拟(MATLAB实现)
开发语言·matlab
昵称已被吞噬~‘(*@﹏@*)’~21 小时前
【RL+空战】学习记录03:基于JSBSim构造简易空空导弹模型,并结合python接口调用测试
开发语言·人工智能·python·学习·深度强化学习·jsbsim·空战
短剑重铸之日21 小时前
《SpringBoot4.0初识》第一篇:前瞻与思想
java·开发语言·后端·spring·springboot4.0
苦藤新鸡21 小时前
8.最长的无重复字符的子串
c++·力扣
2501_9418779821 小时前
从配置热更新到运行时自适应的互联网工程语法演进与多语言实践随笔分享
开发语言·前端·python
lsx20240621 小时前
Python 运算符详解
开发语言
程序炼丹师1 天前
CMakeLists中 get_filename_component详解
开发语言
꧁Q༒ོγ꧂1 天前
C++ 入门完全指南(四)--函数与模块化编程
开发语言·c++
汉克老师1 天前
GESP2025年12月认证C++八级真题与解析(判断题8-10)
c++·快速排序··lcs·gesp八级·gesp8级
listhi5201 天前
对LeNet-5的matlab实现,识别MINST手写数字集
开发语言·matlab