首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C++引用专题(上):详解C++传值返回和传引用返回

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

作者头像
艾莉丝努力练剑
发布2025-11-13 09:32:19
发布2025-11-13 09:32:19
1520
举报
文章被收录于专栏:C / C++C / C++

🔥个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》《数据结构与算法》C语言刷题12天IO强训LeetCode代码强化刷题C/C++干货分享&学习过程记录 🍉学习方向:C/C++方向 ⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平

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


C++的两个参考文档:

老朋友(非官方文档):cplusplus 官方文档(同步更新):cppreference

正文

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

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

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

一、传值返回详解

1、基本概念

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

2、典型代码示例
代码语言:javascript
复制
// 基本类型传值返回
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): 编译器消除临时对象的构造和拷贝
代码语言:javascript
复制
std::string func() 
{
    return std::string("hello");  // 可能直接在调用方内存构造
}
  • NRVO (Named Return Value Optimization): 对命名局部变量的优化
代码语言:javascript
复制
std::string func() 
{
    std::string s = "hello";
    return s;  // 可能直接在调用方内存构造
}
5、适用场景
  • 返回基本类型(int、double等)
  • 返回小型结构体或简单对象
  • 需要返回独立副本的情况
  • 返回局部变量时
6、优点
  • 安全性高,不会产生悬空引用
  • 接口清晰,调用方获得独立对象
  • 现代C++编译器优化后性能良好
7、缺点
  • 对于大型对象可能有拷贝开销(未优化时)
  • 无法通过返回值修改原对象

二、传引用返回详解

1、基本概念

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

2、典型代码示例
代码语言:javascript
复制
// 返回静态变量的引用(安全)
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、生命周期注意事项
代码语言:javascript
复制
// 危险示例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、默认优先使用传值返回
代码语言:javascript
复制
// 现代C++编译器能很好优化
std::vector<int> getData() 
{
    return {1, 2, 3};  // 依赖RVO/NRVO
}
2、明确使用引用返回的场景
代码语言:javascript
复制
// 场景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正确性
代码语言:javascript
复制
// 只读访问用const引用
const std::string& getName() const;

// 需要修改用非const引用
std::string& getMutableName();
4、C++11后的改进
代码语言:javascript
复制
// 移动语义支持
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、性能关键代码的考量
代码语言:javascript
复制
// 参数+返回优化
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++传值返回和传引用返回相关的内容,希望对大家有所帮助。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正文
    • 一、传值返回详解
      • 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、性能关键代码的考量:
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档