值返回与引用返回(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;
}

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

总结

场景 值返回 引用返回
返回计算结果 ✅ 推荐 ⚠️ 需确保对象有效
返回局部创建的对象 ✅ 安全 ❌ 绝对禁止
返回输入参数 ⚠️ 可能低效 ✅ 高效
返回静态数据 ⚠️ 可能拷贝 ✅ 高效
链式调用 ❌ 不能链式 ✅ 支持链式
函数修改参数 ❌ 不能修改 ✅ 可以修改
多线程安全 ✅ 线程安全 ⚠️ 需同步访问
相关推荐
qq_423233905 分钟前
C++与Python混合编程实战
开发语言·c++·算法
m0_7155753418 分钟前
分布式任务调度系统
开发语言·c++·算法
csbysj202035 分钟前
选择(Selectable)
开发语言
CSDN_RTKLIB39 分钟前
简化版unique_ptr说明其本质
c++
naruto_lnq39 分钟前
泛型编程与STL设计思想
开发语言·c++·算法
:Concerto1 小时前
JavaSE 注解
java·开发语言·sprint
m0_748708052 小时前
C++中的观察者模式实战
开发语言·c++·算法
时光找茬2 小时前
【瑞萨AI挑战赛-FPB-RA6E2】+ 从零开始:FPB-RA6E2 开箱测评与 e2 studio 环境配置
c++·单片机·边缘计算
qq_537562672 小时前
跨语言调用C++接口
开发语言·c++·算法
wjs20242 小时前
DOM CDATA
开发语言