当前位置: 首页 > news >正文

C++引用专题(上):详解C++传值返回和传引用返回


🔥个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、C/C++干货分享&学习过程记录

🍉学习方向:C/C++方向

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平



前言:本专栏记录了博主C++从初阶到高阶完整的学习历程,会发布一些博主学习的感悟、碰到的问题、重要的知识点,和大家一起探索C++这门程序语言的奥秘。这个专栏将记录博主C++语法、高阶数据结构、STL的学习过程,正所谓“万丈高楼平地起”嘛,我们话不多说,继续进行C++阶段的学习。本文我们不讲C++主线的内容,我们来拓展一下或者说整理一下我们学习时C/C++时经常会提到的一些专有名词,例如形参、实参,显式类型转换和隐式类型转换类型转换,内置类型、引用、传值返回和传引用返回等等。


  C++的两个参考文档:

老朋友(非官方文档):cplusplus

官方文档(同步更新):cppreference


目录

正文

一、传值返回详解

1、基本概念

2、典型代码示例

3、底层工作原理

4、编译器优化(RVO/NRVO)

5、适用场景

6、优点

7、缺点

二、传引用返回详解

1、基本概念

2、典型代码示例

3、底层工作原理

4、生命周期注意事项

5、适用场景

6、优点

7、缺点

三、对比总结表

四、C++实践

1、默认优先使用传值返回:

2、明确使用引用返回的场景:

3、结合const正确性:

4、C++11后的改进:

5、性能关键代码的考量:

结尾


正文

博主之前写了传值返回和传引用返回相关的内容,只不过那是在C++初识部分介绍的,比较简略:

【C/C++】初识C++(二):深入详解缺省参数(默认参数)函数重载、引用(重头戏)

【C/C++】初识C++(三):C++入门内容收尾——const引用,指针和引用关系梳理,inline(内联函数),nullptr替代NULL

一、传值返回详解

1、基本概念

传值返回是指函数返回对象的一个副本,调用方获得的是与原对象完全独立的新对象。

2、典型代码示例

// 基本类型传值返回
int add(int a, int b) 
{return a + b;  // 返回int类型的值
}// 对象传值返回
std::string createGreeting(const std::string& name) 
{return "Hello, " + name + "!";  // 返回新构造的string对象
}// 返回局部对象(安全)
std::vector<int> generateNumbers() 
{std::vector<int> nums {1, 2, 3, 4, 5};return nums;  // 返回拷贝(可能被RVO优化)
}

3、底层工作原理

  1. 函数内部创建要返回的对象

  2. 将该对象拷贝到调用方的接收位置(可能被编译器优化)

  3. 函数栈帧销毁,局部变量被清理

4、编译器优化(RVO/NRVO)

  • RVO (Return Value Optimization): 编译器消除临时对象的构造和拷贝

std::string func() 
{return std::string("hello");  // 可能直接在调用方内存构造
}
  • NRVO (Named Return Value Optimization): 对命名局部变量的优化

std::string func() 
{std::string s = "hello";return s;  // 可能直接在调用方内存构造
}

5、适用场景

  • 返回基本类型(int、double等)

  • 返回小型结构体或简单对象

  • 需要返回独立副本的情况

  • 返回局部变量时

6、优点

  • 安全性高,不会产生悬空引用

  • 接口清晰,调用方获得独立对象

  • 现代C++编译器优化后性能良好

7、缺点

  • 对于大型对象可能有拷贝开销(未优化时)

  • 无法通过返回值修改原对象

二、传引用返回详解

1、基本概念

传引用返回是指函数返回对象的引用(别名),调用方获得的是对原对象的直接引用。

2、典型代码示例

// 返回静态变量的引用(安全)
const std::string& getVersion() {static const std::string ver = "1.0.0";return ver;
}// 返回成员变量的引用
class Container {std::vector<int> data;
public:// const引用返回const std::vector<int>& getData() const { return data; }// 非const引用返回(允许修改)std::vector<int>& getMutableData() { return data; }
};// 返回参数引用(需确保参数生命周期)
const std::string& longerString(const std::string& a, const std::string& b) {return a.length() > b.length() ? a : b;
}

3、底层工作原理

  1. 函数计算要返回的引用(地址)

  2. 将该地址返回给调用方

  3. 调用方通过引用直接访问原对象

4、生命周期注意事项

// 危险示例1:返回局部变量引用
const int& dangerous1() {int x = 42;return x;  // x将被销毁!
}// 危险示例2:返回临时对象引用
const std::string& dangerous2() {return "temporary";  // 临时对象将销毁!
}// 危险示例3:返回悬空指针的引用
const std::string& dangerous3() {std::string* s = new std::string("hello");return *s;  // 内存泄漏风险
}

5、适用场景

  • 返回类成员变量

  • 返回静态/全局变量

  • 返回参数中生命周期有保障的对象

  • 需要允许调用者修改原对象时

  • 返回大型对象避免拷贝时

6、优点

  • 无拷贝开销,性能高

  • 允许修改原对象(非const引用时)

  • 可以用于实现链式调用

7、缺点

  • 必须确保被引用对象的生命周期

  • 不当使用会导致未定义行为

  • 接口契约更复杂(需要文档说明生命周期

三、对比总结表

比较维度传值返回传引用返回
返回内容对象副本对象别名
拷贝开销可能有(但常被优化)
修改原对象不能可以(非const引用)
安全性需注意生命周期
适用对象大小小型对象中大型对象
典型用例工厂函数、计算函数访问器、链式调用
RVO优化支持不适用
C++11移动语义可结合使用不适用

四、C++实践

1、默认优先使用传值返回

// 现代C++编译器能很好优化
std::vector<int> getData() 
{return {1, 2, 3};  // 依赖RVO/NRVO
}

2、明确使用引用返回的场景

// 场景1:返回类成员
class Config 
{std::string path;
public:const std::string& getPath() const { return path; }
};// 场景2:链式调用
class Builder 
{std::string data;
public:Builder& append(const std::string& s) {data += s;return *this;}
};

3、结合const正确性

// 只读访问用const引用
const std::string& getName() const;// 需要修改用非const引用
std::string& getMutableName();

4、C++11后的改进

// 移动语义支持
std::unique_ptr<Resource> createResource() 
{auto res = std::make_unique<Resource>();res->initialize();return res;  // 移动而非拷贝
}// 返回右值引用
std::vector<int>&& extractData() 
{std::vector<int> temp;// ...填充数据return std::move(temp);  // 明确所有权转移
}

5、性能关键代码的考量

// 参数+返回优化
void computeResult(Input in, Result& out) 
{// 直接填充out避免拷贝
}// 或者返回智能指针
std::shared_ptr<BigData> createBigData() 
{return std::make_shared<BigData>();
}

我们在选择具体的返回方式需要综合考虑对象生命周期、性能需求、接口设计等多个因素。


结尾

往期回顾:

【C/C++】C++引用和指针的对比

【C/C++】形参、实参相关内容整理

【C/C++】Dev-C++的安装与使用以及快捷键整理

【日常问题解决方案】VS2022不小心解决方案资源管理器把关掉了怎么办

VS2022进行监视功能的步骤

结语:本文内容到这里就全部结束了。本文我们重新整理了C++传值返回和传引用返回相关的内容,希望对大家有所帮助。

http://www.dtcms.com/a/319885.html

相关文章:

  • JavaScript核心概念解析:从基础语法到对象应用
  • 部署 AddressSanitizer(ASan)定位内存泄漏、内存越界
  • Java+Vue合力开发固定资产条码管理系统,移动端+后台管理,集成资产录入、条码打印、实时盘点等功能,助力高效管理,附全量源码
  • 【保姆级喂饭教程】python基于mysql-connector-python的数据库操作通用封装类(连接池版)
  • SPI TFT全彩屏幕驱动开发及调试
  • Sentinel原理之责任链详解
  • imx6ull-驱动开发篇12——GPIO子系统驱动LED
  • C++高频知识点(十五)
  • Qwen-Image开源模型实战
  • 【Floyd】Shortest Routes II
  • 显卡服务器的作用主要是什么?-哈尔滨云前沿
  • 使用内网穿透工具1分钟上线本地网站至公网可访问,局域网电脑变为服务器
  • Mysql数据仓库备份脚本
  • 2.7 (拓展)非父子通信(事件总线和provide-inject)详解
  • 2025 年华数杯全国大学生数学建模竞赛B题 网络切片无线资源管理方案设计--完整成品、思路、代码、模型结果分享,仅供学习~
  • java 生成pdf导出
  • 【tip】font-family的设置可能导致的文字奇怪展示
  • 《P3275 [SCOI2011] 糖果》
  • 运营商面向政企客户推出的DICT项目
  • 【ee类保研面试】数学类---概率论
  • 5G专网提高产业生产力
  • 别墅泳池设计综述:从理念创新到技术实现的系统性研究
  • 基于 PyTorch 从零实现 Transformer 模型:从核心组件到训练推理全流程
  • Java 大视界 -- Java 大数据在智能安防门禁系统中的人员行为分析与异常事件预警(385)
  • nvm安装,nvm管理node版本
  • Java设计模式总结
  • 【设计模式精解】什么是代理模式?彻底理解静态代理和动态代理
  • Vue自定义流程图式菜单解决方案
  • [激光原理与应用-171]:测量仪器 - 能量型 - 激光能量计(单脉冲能量测量)
  • DicomObjects COM 8.XX