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

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

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

我是"借来看一眼",

还是"要动它",

还是"要收下它"。

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

相关推荐
2601_949868362 小时前
Flutter for OpenHarmony 剧本杀组队App实战04:发起组队表单实现
开发语言·javascript·flutter
一匹电信狗2 小时前
【C++】CPU的局部性原理
开发语言·c++·系统架构·学习笔记·c++11·智能指针·新特性
m0_561359672 小时前
C++代码冗余消除
开发语言·c++·算法
毕设源码-郭学长2 小时前
【开题答辩全过程】以 基于Python爬取学院师资队伍信息的设计与分析为例,包含答辩的问题和答案
开发语言·python
会开花的二叉树2 小时前
吃透Reactor多线程:EventLoop_Channel_ThreadPool协作原理
开发语言·c++·tcp/ip·servlet
Jm_洋洋2 小时前
【C++进阶】虚函数、虚表与虚指针:多态底层机制剖析
java·开发语言·c++
老骥伏枥~2 小时前
C# 控制台:Console.ReadLine / WriteLine
开发语言·c#
近津薪荼2 小时前
优选算法——滑动窗口1(单调性)
c++·学习·算法
头发还没掉光光2 小时前
Linux 高级 IO 深度解析:从 IO 本质到 epoll全面讲解
linux·服务器·c语言·c++