[Effective C++]条款20:宁以 pass-by-reference-to-const替换 pass-by-value

.
在C++中,函数参数与返回值的数据传递的方式,对程序的性能和正确性有着重要影响。C++默认使用pass-by-value(传值)的方式传递参数。但这种方式在某些情况下会导致性能问题和对象切割问题。
C++推荐使用pass-by-reference-to-const(传常量引用)的方式来传递参数。

1、C++默认传值方式的问题

1.1、多次调用拷贝构造函数

  • 当使用pass-by-value传递参数时,C++会调用参数的拷贝构造函数来创建一个副本。如果传递的是一个复杂的对象(例如包含大量数据的类对象),拷贝构造函数的调用会导致性能问题,尤其是在频繁调用的情况下。
#include <iostream>
#include <string>class MyClass {
public:MyClass() {std::cout << "Default Constructor" << std::endl;}MyClass(const MyClass& other) {std::cout << "Copy Constructor" << std::endl;}~MyClass() {std::cout << "Destructor" << std::endl;}
};void func(MyClass obj) {// 使用obj
}int main() {MyClass obj;func(obj);  // 调用拷贝构造函数return 0;
}输出:
Default Constructor
Copy Constructor
Destructor
Destructor

1.2、对象切割问题

  • 对象切割问题发生在传递派生类对象给基类参数时。如果使用pass-by-value传递参数,派生类会被切割成基类对象,丢失派生类的特有部分。
  • 原因:当函数参数类型是基类时,编译器会调用基类的拷贝构造函数来创建基类对象的副本。即使基类有虚函数,基类对象的虚表指针会被重置为指向基类的虚表,导致派生类的虚函数无法被调用。
#include <iostream>class Base {
public:virtual void print() const {std::cout << "Base" << std::endl;}
};class Derived : public Base {
public:void print() const override {std::cout << "Derived" << std::endl;}
};void func(Base obj) {obj.print();  // 总是调用Base的print
}int main() {Derived d;func(d);  // 对象切割,丢失Derived部分return 0;
}输出:
Base

2、使用pass-by-reference-to-const替换pass-by-value

  • 为了避免上述问题,C++体检使用pass-by-reference-to-const来传递参数,避免不必要的拷贝和对象切割问题
  • 原理:在底层实现上,引用是通过指针来实现的,编译器会将引用转换成指针操作,传递的是对象地址。
    • 指针大小是固定的4字节,无论对象有多大,传递引用的开销非常小。使用const常量修饰可避免对象修改。
    • 因为传值引用对象直接指向原始对象,不会创建新的基类对象。
class Base
{
public:virtual void print() const{std::cout << "Base" << std::endl;}
};class Derived : public Base
{
public:void print() const override{std::cout << "Derived" << std::endl;}
};void func(const Base &obj)
{obj.print(); // 总是调用Base的print
}int main()
{Derived d;func(d); // 对象切割,丢失Derived部分return 0;
}输出:
Derived

3、适合pass-by-value的情况

  • 内置类型:对于内置类型(如int、double、char等),使用pass-by-value通常更高效,因为拷贝这些类型的开销很小。
  • 小型对象:对于小型对象(如std::pair、std::tuple等),使用pass-by-value也可能更高效。
#include <iostream>void func(int x) {std::cout << "Value: " << x << std::endl;
}int main() {int a = 10;func(a);  // 对于内置类型,使用pass-by-valuereturn 0;
}

思维导图笔记:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38033.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文字变央视级语音转换工具

大家在制作短视频、广告宣传、有声读物、自媒体配音、学习辅助等场景的时候&#xff0c;经常会需要用到配音来增强视频的表现力和吸引力。然而&#xff0c;市面上的一些配音软件往往需要收费&#xff0c;这对于很多初学者或者预算有限的朋友来说&#xff0c;无疑增加了一定的负…

邂逅书香:在诗韵与青春中找寻心灵归处

在信息如洪流般奔涌的当下&#xff0c;我们的灵魂时常在喧嚣中漂泊&#xff0c;渴望一处宁静港湾。而书籍&#xff0c;一直以来都是人类最忠诚的精神伴侣。今天&#xff0c;要为诗歌爱好者和青春文学迷们带来两份特别的礼物——《韵之队诗集》与《青春与爱共舞》&#xff0c;它…

国科大——计网(0812)——实验作业

**前沿&#xff1a;**此博客记录了24—25年度秋季学期计算机网络&#xff08;0812&#xff09;课程的实验作业&#xff0c;所提供的材料仅供参考。 0 实验题目 本次实验总共提供了四个可选的题目&#xff0c;即BGP分析实验&#xff0c;BGP 前缀劫持攻击及检测实验&#xff0c…

新能源汽车高压液体加热器总成技术解析及未来发展趋势

引言 新能源汽车的快速发展对热管理系统提出了更高要求&#xff0c;高压液体加热器作为核心组件&#xff0c;直接影响车辆低温性能、电池寿命及用户体验。本文以实际产品为例&#xff0c;结合行业数据与技术趋势&#xff0c;深度解析高压液体加热器的技术原理、市场现状及未来…

蓝桥杯 数字接龙

问题描述 小蓝最近迷上了一款名为《数字接龙》的迷宫游戏。 游戏在一个大小为 N N 的格子棋盘上展开&#xff0c;其中每一个格子处都有一个 0 到 K-1 之间的整数。 游戏规则如下&#xff1a; 从左上角 (0, 0) 出发&#xff0c;目标是到达右下角 (N-1, N-1)。 每一步可以选…

SysVinit和Systemd的系统运行级别

Linux运行级别 SysVinit系统(init守护进程)Linux系统运行级别SysVinit系统(init守护进程)查看Linux运行级别SysVinit系统(init守护进程)修改运行级别&#xff1a; Systemd守护进程Linux系统运行级别systemd查看运行级别Systemd查看系统当前运行级别 systemd修改运行级别multi-u…

SAP SD学习笔记33 - 预詑品(寄售物料),预詑品引渡(KB),预詑品出库(KE)

上一章讲了Service品目。 SAP SD学习笔记32 - Service品目(服务产品&#xff09;-CSDN博客 本章继续讲SAP SD的知识 - 预詑品(寄售物料)。 目录 1&#xff0c;预詑品概要 1-1&#xff0c;预詑品(寄售物料)的概念 1-2&#xff0c;预詑品的4种业务 1-3&#xff0c;受托品与…

DeiT:数据高效的图像Transformer及其工作原理详解

DeiT&#xff1a;数据高效的图像Transformer及其工作原理详解 随着Transformer架构在自然语言处理&#xff08;NLP&#xff09;领域的巨大成功&#xff0c;研究者们开始探索其在计算机视觉领域的应用。Vision Transformer&#xff08;ViT&#xff09;是最早将Transformer直接应…

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的异常处理:全局异常与自定义异常

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…

【Mybatis-plus】在mybatis-plus中 if test标签如何判断 list不为空

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

Lineageos 22.1(Android 15)制定应用强制横屏

一、前言 有时候需要系统的某个应用强制衡平显示&#xff0c;不管他是如何配置的。我们只需要简单的拿到top的Task下面的ActivityRecord&#xff0c;并判断包名来强制实现。 二、调整wms com.android.server.wm.DisplayRotation /*** Given an orientation constant, return…

HTML网页代码预览器

HTML网页代码预览器 可以用于学习和实验HTML和CSS&#xff0c;比较方便。源码参考自网络。 功能 实时预览&#xff1a;当你在左侧的“代码编辑器”中输入代码时&#xff0c;右侧的“预览窗口”会实时显示你的网页效果&#xff08;注意&#xff0c;不能体现嵌入的JavaScript运…

Arm Linux ceres库编译

由于工作需要&#xff0c;需在国产化系统上编译ceres库&#xff0c;手上有一块树莓派&#xff0c;就在树莓派上面进行测试编译ceres库&#xff0c;总体来说比较顺利。只出现了一点小问题 参考链接&#xff1a; Ceres中文教程-安装 按照上面Linux编译过程 目录 1、在线安装依赖…

【算法学习计划】动态规划 -- 背包问题(01背包和完全背包)

目录 DP41 【模板】01背包 leetcode 416.分割等和子集 leetcode 494.目标和 leetcode 1049.最后一块石头的重量Ⅱ DP42 【模板】完全背包 leetcode 322.零钱兑换 leetcode 518.零钱兑换Ⅱ leetcode 279.完全平方数 今天&#xff0c;我们将通过 8 道题目&#xff0c;来带…

138. 随机链表的复制

题目&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节…

网络HTTPS协议

Https HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是 HTTP 协议的加密版本&#xff0c;它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说&#xff1a; • 加密通信&#xff1a;在用户请求访问一个 HTTPS 网站时&#xff0c;客户端&#x…

19921 多重背包

19921 多重背包 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;动态规划、背包问题 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N …

C/C++蓝桥杯算法真题打卡(Day5)

一、P8772 [蓝桥杯 2022 省 A] 求和 - 洛谷 算法代码&#xff1a; #include<bits/stdc.h> // 包含标准库中的所有头文件&#xff0c;方便编程 using namespace std; // 使用标准命名空间&#xff0c;避免每次调用标准库函数时都要加 std::int main() {int n; …

【大模型基础_毛玉仁】3.5 Prompt相关应用

目录 3.5 相关应用3.5.1 基于大语言模型的Agent3.5.2 数据合成3.5.3 Text-to-SQL3.5.4 GPTs 3.5 相关应用 Prompt工程应用广泛&#xff0c;能提升大语言模型处理基础及复杂任务的能力&#xff0c;在构建Agent、数据合成、Text-to-SQL转换和设计个性化GPTs等方面不可或缺。 . …

主成分分析PCA与奇异值分解SVD

线性代数 SVD 奇异值分解&#xff08;Singular Value Decomposition&#xff0c;简称 SVD&#xff09;是线性代数中的一种基本工具&#xff0c;它将任意一个 (m * n) 矩阵 (A) 分解成三个简单矩阵的乘积&#xff0c;即 其中&#xff1a; (U) 是一个 (m*m) 的正交&#xff08…