当前位置: 首页 > news >正文

C++ class传值和传引用的详细介绍

在 C++ 中,class(类对象)的传值传引用是两种截然不同的参数传递方式,它们在性能、内存管理和行为上有着本质的区别。

简单来说:传值是“复制一份”,传引用是“取个别名”。

以下是详细的对比分析:

1. 核心区别概览

表格

特性传值传引用 (&)
机制创建对象的副本(拷贝)对象的别名(直接操作原对象)
修改影响函数内修改不影响外部对象函数内修改直接影响外部对象
性能开销(需调用拷贝构造函数)(无拷贝,仅传递地址)
内存占用占用双倍内存 (原对象+副本)几乎不占额外内存
安全性高 (外部数据受保护)较低 (外部数据可能被意外修改)
多态性会导致对象切片(丢失派生类信息)支持多态(保留完整信息)

2. 深入解析

📦 传值

当你按值传递一个类对象时,C++ 会调用该类的拷贝构造函数来创建一个完全独立的副本。

  • 优点
    • 数据安全:函数内部无论怎么折腾,都不会影响原始数据。
    • 语义清晰:适合传递小型对象或不需要修改的场景。
  • 缺点
    • 性能差:如果类很大(包含大量成员变量或动态内存),拷贝操作非常耗时。
    • 对象切片:如果传递的是派生类对象给基类形参,派生类特有的部分会被“切掉”,导致多态失效。

🔗 传引用

传递引用实际上是传递对象的内存地址,但在语法上看起来像直接操作变量。

  • 优点
    • 高性能:没有拷贝开销,无论对象多大,传递效率都一样高。
    • 支持多态:可以传递派生类对象给基类引用,正确调用虚函数。
    • 修改原值:允许函数直接修改调用者的数据(如果需要的话)。
  • 缺点
    • 副作用风险:如果不小心,可能会意外修改外部数据。

3. 代码示例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

#include <iostream>

#include <string>

#include <vector>

classStudent {

public:

std::string name;

intage;

Student(std::string n,inta) : name(n), age(a) {}

// 拷贝构造函数(用于演示传值时的拷贝行为)

Student(constStudent& other) : name(other.name), age(other.age) {

std::cout <<"📋 [拷贝构造函数被调用]"<< std::endl;

}

};

// --- 1. 传值 ---

// 这里的 s 是 originalStudent 的副本

voidmodifyByValue(Student s) {

s.name ="Modified_Value";

s.age = 99;

std::cout <<"函数内(值): "<< s.name <<", "<< s.age << std::endl;

}

// --- 2. 传引用 (非常用) ---

// 这里的 s 是 originalStudent 的别名

voidmodifyByReference(Student& s) {

s.name ="Modified_Reference";

s.age = 88;

std::cout <<"函数内(引用): "<< s.name <<", "<< s.age << std::endl;

}

// --- 3. 常量引用 (最佳实践) ---

// 既避免了拷贝,又防止了修改

voidprintStudent(constStudent& s) {

// s.name = "Error"; // 编译错误:不能修改 const 对象

std::cout <<"函数内(只读): "<< s.name <<", "<< s.age << std::endl;

}

intmain() {

Student originalStudent("Alice", 20);

std::cout <<"原始数据: "<< originalStudent.name <<", "<< originalStudent.age << std::endl;

std::cout <<"--- 调用传值函数 ---"<< std::endl;

modifyByValue(originalStudent);

// originalStudent 未被修改,但触发了拷贝构造

std::cout <<"调用后: "<< originalStudent.name <<", "<< originalStudent.age << std::endl << std::endl;

std::cout <<"--- 调用传引用函数 ---"<< std::endl;

modifyByReference(originalStudent);

// originalStudent 被修改了

std::cout <<"调用后: "<< originalStudent.name <<", "<< originalStudent.age << std::endl;

return0;

}

4. 什么时候用哪个?(最佳实践)

在实际开发中,请遵循以下规则:

  • 首选:const引用 (const ClassName& obj)
    • 场景:绝大多数情况。当你只需要读取对象数据,不需要修改它时。
    • 理由:避免了昂贵的拷贝开销,同时保证了数据安全(不会被函数修改)。
    • 例子:void printData(const std::vector<int>& data);
  • 次选:非const引用 (ClassName& obj)
    • 场景:当你需要在函数内部修改对象状态时。
    • 理由:高效且意图明确(调用者知道数据会被改)。
    • 例子:void updateConfig(Config& cfg);
  • 最后:传值 (ClassName obj)
    • 场景:
    • 对象非常小(如只包含 1-2 个int的类)。
    • 你确实需要一个副本,并且要在函数内随意修改而不影响原对象。
    • 注意:对于像std::vectorstd::string或大型自定义类,永远不要按值传递。
http://www.jsqmd.com/news/1393277/

相关文章:

  • Obsidian看板插件:把散落笔记变成一目了然的「任务流水线」
  • 2026年8月综合盘点 定远县二手车收购服务商推荐 - 品牌品鉴馆
  • 达梦数据库SQL脚本执行全解析:从图形化到命令行的实战指南
  • 微信聊天记录如何永久保存?WeChatMsg 三步导出与年度报告全攻略
  • 西藏6日珠峰纯玩小团路线:99%的游客入藏旅游首选 - 生活动态圈
  • .NET 5 安装与开发环境搭建全攻略:从零到项目实战
  • KMS_VL_ALL_AIO 激活指南:5 分钟搞定 Windows 与 Office 的激活难题
  • 千问开放平台上线!夸克网盘、夸克扫描王首批接入
  • Python爬虫实战进阶:从基础到分布式与反爬策略
  • 免费获取苹方字体:PingFangSC字体包在Windows与网页的完整落地指南
  • python的工业过程控制场景模拟第一百三十九篇:编写仿真程序测试多回路之间信号干扰,评估接地滤波方案改善效果。
  • 深圳做企业官网靠谱网站建设公司2026年口碑前三详细介绍 - 品牌品鉴馆
  • C++之string和char的使用及区别
  • Markdown LaTeX公式语法全解析:从基础到实战应用
  • KVM宿主机与虚拟机文件传输方案全解析:从SCP到VirtIO-FS
  • 网盘下载加速实测:八大网盘直链一键获取,从“一夜下不完“到分钟级搞定
  • 2026上海爱格全屋定制怎么选工厂:诺凡与主流方案对比解析 - 生活动态圈
  • 128、YOLOv12核心架构深度解剖(三):R-ELAN模块替代C3k2/C2f的设计哲学与梯度流分析——手把手推导梯度传播路径并验证涨点效果
  • 快速生成 OpenCore EFI 的终极指南:OpCore-Simplify 让黑苹果配置不再劝退
  • 一个单文件搞定Windows和Office激活:我用KMS_VL_ALL_AIO的真实体验
  • OmenSuperHub实测:惠普暗影精灵卸载官方OGH之后,风扇功耗背光还能这样玩
  • reverse_markdown命令行用法详解:轻松实现文件与管道转换
  • 从0到1部署Snipe-IT:7步跑通资产全生命周期管理,IT管理员必备的免费开源方案
  • IdentityManager完全指南:现代用户与身份管理工具的终极入门
  • 2026年8月综合盘点:留学生集运避坑参考 - 品牌品鉴馆
  • 鸣潮自动化工具ok-ww完全指南:免费解放双手的后台自动战斗助手
  • ESP32-WROOM-32E-N8R2:一款自带PSRAM的经典Wi-Fi蓝牙模组
  • G-Helper 无法启动?5 个步骤一次搞定华硕笔记本控制工具启动修复
  • BRD文件查看器 OpenBoardView 实操记录:从打不开文件到找到那颗坏芯片
  • Ubuntu GRUB启动项冗余清理:原理、方法与故障排查