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

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

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

我是"借来看一眼",

还是"要动它",

还是"要收下它"。

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

相关推荐
FeBaby8 小时前
ReentrantLock 与 synchronized 底层实现对比图解
开发语言·c#
jaycyj8 小时前
pytest
开发语言·python
A_aspectJ8 小时前
【Java基础开发】基于 Java Swing +MySQL + JDBC 版实现图书管理系统
java·开发语言·mysql
yinbinggang8 小时前
vmware安装虚拟机
c++
Gary Studio8 小时前
安卓HAL编译流程
开发语言·python
我是无敌小恐龙8 小时前
Java SE 零基础入门Day06 方法重载+Debug调试+String字符串全套API详解(超全干货)
java·开发语言·人工智能·python·transformer·无人机·量子计算
AI+程序员在路上8 小时前
Qt6读取rtsp视频流的几种方法
开发语言·qt6.3
码农飞哥8 小时前
从Java后端到AI应用开发,我这两年做了什么
java·开发语言·人工智能
胡童嘉8 小时前
C语言考研《谭浩强C语言》教材第一章理论+实践汇总
c语言·开发语言·考研
初心未改HD8 小时前
Go语言Slice切片底层原理深度解析
开发语言·golang