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++ 参数传递的本质不是语法问题,而是:

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

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

我是"借来看一眼",

还是"要动它",

还是"要收下它"。

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

相关推荐
chao1898442 分钟前
基于MATLAB的音频信号AM调制与解调实现
开发语言·matlab·音视频
雨落在了我的手上4 分钟前
初识java(八):数组的定义与使用
java·开发语言
贵州晓智信息科技4 分钟前
曼德勃罗集的 Three.js 实现
开发语言·javascript·ecmascript
xiaoshuaishuai85 分钟前
C# CUDA 到 OpenCL 迁移
开发语言·windows·c#
闻缺陷则喜何志丹5 分钟前
【图论 树 启发式合并】P7165 [COCI2020-2021#1] Papričice|普及+
c++·算法·启发式算法·图论··洛谷
AI科技星6 分钟前
基于平行素数对等腰梯形网格拓扑的完备性证明哥德巴赫猜想1+1
c语言·开发语言·网络·量子计算·agi
聆风吟º6 分钟前
【C标准库】深入理解C语言 isdigit函数详解:判断字符是否为数字
c语言·开发语言·库函数·isdigit
alexwang2117 分钟前
AT_abc458_d [ABC458D] Chalkboard Median题解
c++·算法·题解·atcoder
故事和你918 分钟前
洛谷-【图论2-4】连通性问题1
开发语言·数据结构·c++·算法·动态规划·图论
RSCompany9 分钟前
Frida 17 以后 Python API 跑旧版 JS 报 Java is not defined ?一行 import 直接恢复 Frida 16 体验
开发语言·python·逆向·hook·frida·android逆向·frida17