C++ 函数参数传递方式总结:什么时候用值传递、引用、const 引用?

在 C++ 开发中,一个经常让人困惑的问题是:

函数参数到底该写 TT&,还是 const T&

很多人只记住一句话:
"大对象用 const 引用,小对象用值传递",

但背后的逻辑如果不理解,实际写代码时还是会犹豫。

这篇文章我们从 性能、语义、工程实践 三个角度,把参数传递方式一次讲清楚。

一、C++ 三种常见参数形式

1. 值传递(Pass by Value)

cpp 复制代码
void f(T x);

特点:

  • 拷贝一份对象
  • 函数内部改 x,不会影响外部
  • 简单直接

适用场景:

  • 小类型(int / double / bool / enum)
  • 函数需要"收下这份数据"
  • 要存入成员变量 / 容器

2. 引用传递(Pass by Reference)

cpp 复制代码
void f(T& x);

特点:

  • 不拷贝,直接操作原对象
  • 可以修改调用者的数据

适用场景:

  • 明确要 修改调用者对象
  • 工具函数 / 算法函数 / swap / normalize 等

3. 常量引用(Pass by Const Reference)

cpp 复制代码
void f(const T& x);

特点:

  • 不拷贝
  • 不允许修改
  • 性能好 + 语义清晰

适用场景:

  • 大对象只读访问
  • 打印 / 比较 / 计算 / 日志 / 序列化
  • std::string / vector / map / 自定义类

二、为什么不用 const T(值传 const)?

很多人会写:

cpp 复制代码
void f(const std::string s);

这其实 意义不大,因为:

  • 仍然会拷贝
  • const 只限制函数内部
  • 外部对象本来就不会被影响

所以:

const T 不能省拷贝,
const T& 才能省拷贝。

三、性能视角:什么时候会浪费资源?

大对象

cpp 复制代码
void f(std::string s);        // 会拷贝
void f(const std::string& s); // 不拷贝

拷贝 string / vector 可能涉及:

  • 内存分配
  • 数据复制
  • 构造析构

这是真正的资源浪费。

小对象

cpp 复制代码
void f(int x);          // 推荐
void f(const int& x);   // 没必要

原因:

  • int 只有 4 字节
  • 引用反而传 8 字节地址
  • CPU 寄存器传值更快

四、现代 C++ 的一个重要写法:值传 + move

当函数需要 保存参数 时,推荐这样写:

cpp 复制代码
class User {
    std::string name;
public:
    void setName(std::string n) {
        name = std::move(n);
    }
};

优点:

  • 左值调用:会拷贝
  • 右值调用:直接移动
  • 接口统一,调用舒服

这是现代 C++ 很常见的工程写法。

五、工程实践决策表

三个判断问题

1. 是否需要修改调用者?
  • 是 → T&

  • 否 → 继续

2. 是否是小类型?
  • 是 → T

  • 否 → 继续

3. 是否要保存参数?
  • 是 → T + move

  • 否 → const T&

六、快速记忆口诀

可以直接背这一句:

改它:T&
小的:T
大的只读:const T&
要收下:T + move

七、典型示例对照

小类型

cpp 复制代码
void setAge(int age);

大对象只读

cpp 复制代码
void print(const std::string& s);

修改对象

cpp 复制代码
void normalize(std::vector<int>& v);

存储对象

cpp 复制代码
void setName(std::string name);

八、总结

C++ 参数传递的本质不是语法问题,而是:

  • 性能
  • 语义表达
  • 工程可维护性

真正的原则不是死记硬背,而是理解:

我是"借来看一眼",

还是"要动它",

还是"要收下它"。

理解这一点,你写出的函数签名就会自然、专业、工程化。

相关推荐
潜创微科技29 分钟前
IT6520:USB-C 转 MIPI 高集成控制器,DP 1.4a 转 MIPI 单芯片搞定 4K120 显示
c语言·开发语言·低延迟·掌机·联阳
Escalating_xu1 小时前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
傲世仙尊1 小时前
System V 进程间通信详解:共享内存、消息队列与信号量(CSDN博客)
linux·开发语言·c++
cvby1 小时前
C++11
开发语言·c++
6Hzlia1 小时前
【Classic 150 刷题计划】 LeetCode 26. 删除有序数组中的重复项 | C++ 快慢双指针经典模板
c++·算法·leetcode
夜不会漫长2 小时前
C++:类和对象(2)
java·javascript·c++
ch.ju2 小时前
Java—idea知识:如何创建新项目
java·开发语言·intellij-idea
无小道2 小时前
C++ 中 `explicit` 关键字详解:彻底理解隐式类型转换
c++·explicit
Evand J3 小时前
【MATLAB例程,图像滤波降噪12】加权中值滑动窗口滤波(WMF)图像降噪,包含滤波质量评价。附代码下载链接
开发语言·图像处理·人工智能·计算机视觉·matlab·滑动窗口·滤波
蒸蒸yyyyzwd3 小时前
cpp 选手秋招学习笔记 day34
c++·八股