effective c++ 笔记 导读/条款2-4

导读

explicit关键字
阻止类型之间的隐式转换。

class B{explict B(int x = 0);
}
Void doSomething(b BObject);
doSomething(B(28)); //正确
doSomething(28); //错误

copy构造和copy赋值

Class Object{Object():  //default构造Object(const Object& obj); //copy构造Object& operator=(const Object& obj);	//copy赋值操作符
}
Object obj1;  //default构造
Object obj2(obj1);  //copy构造
obj1 = obj2; //copy赋值操作符
Object obj3 = obj2; //调用copy构造

如果一个新对象被定义,如obj3,一定会调用一个构造,不能调用赋值。
如果没有新对象被定义,如obj1=obj2,不会有构造调用,调用赋值

bool function(Object obj)

参数obj以传值方式传递,会被复制到函数参数中,又copy构造完成。因此尽量通过传const引用。条款20

条款2 尽量以const,enum,inline替换#define

const替换#define
若用 define 的可能会导致程序出出现多份目标码,而常量不会出现这种情况

1.定义一个常量字符串

const std::string name = "name";

2.class专属常量,为了将作用域限制于类内,并且最多只有一个实体

class object{static const int num = 5;int arr[num];
}

如果是class专属常量又是static且为整数类型(例如ints,chars,bools),只要不取地址,可直接声明并使用.如果去某个class专属常量的地址,必须额外提供定义式。定义式放在.cpp文件而非.h文件

const int object::num;

注:声明时已赋过值,不可再赋值
若编译器不支持声明时赋值,则定义时赋值。
但遇到数组大小这种必须知道值时。使用enum
enmu替换#define

class Object
{
public:enum {num=5};int arr[num];
};

一个属于枚举类型的数值可以充当int使用
取一个 const 的地址是合法的,而取一个 enum 的地址是非法的,而取一个#define 的地址通常也不合法。如果不想别人指针或者引用自己某个整形常量,enum 可以实现这个约束。
inline替换#define
#define函数易误用,纯文本替换需要时刻注意小括号,否则运算符优先级可能出错,甚至

#define MAX(a,b) f((a)+(b) ?(a):(b))
int a = 1, b = 2;
MAX(++a, b);	//a被累加2次
MAX(++a, b+10);	//a被累加1次

使用inline替换

template <typename T>
inline T max(const T& a,const T& b)
{f(a > b ? a: b);
}

总结
1.单纯常量,const对象或enums替换
2.形式函数的宏(macros),inline替换

条款3 尽可能使用const

const作用
const左修饰,最左右修饰
顶层const:指的是const修饰的变量本身是一个常量
底层const:指的是const修饰的变量所指向的对象是一个常量
(声明引用变量都是底层,引用对象是常量)
stl
stl 的迭代器基础是指针,const迭代器与const指针一样。如果希望const T* 指针,则需要const_iterator
函数返回值用const修饰

class N(...);
const  N operator*(const N &lhs, const N &rhs);

防止一些误操作造成赋值。如

N a,b,c;
...
if(a*b = c)		//如果没有const,则隐式转为true

const用于成员函数
为了确认该成员函数可作用于const对象
1.告知哪个函数可以修改成员内容,哪个函数不能
2.使“操作const对象”成为可能

两个成员函数如果只是是常量性不同,可以构成重载。

const T& getXXX() const; //get值不可修改
T& getXXX(); //get值可修改
//可以get同一个成员变量

const成员函数不可以更改对象内任何非静态成员变量。
但两种情况:
1.bitwise constness:成员函数只有在不更改对象的任何成员变量时才可以说是 const,缺陷:若返回的是内部常置针(指针常量)但可以修改指向的对象
2.logical constness:const 成员函数可以修改它所处理的对象的某些值,但只有在客户端侦测不到的情况下才得以如此。(常函数里面除了对常变量的使用,还可能包含一些变量的使用。但是编译器不同意,这时候可以使用 mutable 关键字,使得变量不受函数常量性的约束,可在const函数里修改成员变量)
避免 const 和 non-const 实现的重复
一般的,我们建议在 non-const 函数调用 const 函数的实现。因为const 函数承诺不修改其对象的逻辑状态,但如果去调用 non-const 函数,就可能冒着修改对象的风险

const int& operator[](int idx)const
{return num;
}
int& operator[](int idx)
{//return num;return const_cast<int&>(static_cast<const Object&>(*this)[idx]);
}

static_cast 负责将 *this 对象转换成常对象,这样才能调用常函数
const_cast 负责将常函数返回的常引用转换成普通引用

条款4:确定对象使用前已先被初始化

c++规定,对象的成员变量初始化动作发生在进入构造函数本体之前。

Class Obejct{
public:Object(const std::string & s);
private:std::string str;int num;
}
//std::string先defalut构造,再赋值
Object::Object(const std::string & s){
//赋值,非初始化str = s;num = 0;
}
//std::string直接copy构造,初始化,效率更高
Object::Object(const std::string & s):str(s), num(0)
{}

对多数类型,先调用default再copy赋值,效率不如直接调用一次copy构造。
即对于未在初始列指定初值的成员,编译器会自动调用默认构造函数(也就是说会先调用默认构造函数,在再执行构造函数内的赋值语句)。初值列的效率无疑更高。
对于内置型对象num,初始化和赋值成本相同。但为了一致性,也通过成员初值列初始化
如果成员变量是const或references,为避免需要记住成员变量何时必须在成员初值列中初始化,何时不需要,最简单的做法就是:构造函数使用成员初始化列表来赋值,而不是在构造函数里去赋值(会导致赋值两次)
C++有着非常固定的成员初始化次序。base class 更早于 derived class 被初始化。class成员总是以声明次序被初始化。即使在成员初值列中定义的次序不同,也不会有任何影响
不同编译单元非局部静态对象的初始化顺序
如果某编译单内的某个非局部对象的初始化依赖于另一个编译单元内某个非局部对象,而这个对象可能尚未被初始化,然后就会导致未定义行为。
将每一个非局部静态对象搬到自己专属函数中,函数返回静态对象的引用,然后由用户调用这些函数,而不直接涉及这些对象。类似单例模式
在多线程下,系统会带有不确定性,一个比较好的做法就是:在程序的单线程启动阶段手工调用所有的单例函数

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

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

相关文章

Gateway集成方法以及拦截器和过滤器的使用

前提&#xff1a;请先创建好一个SpringBoot项目 1. 引入依赖 SpringCloud 和 alibabaCloud 、 SpringBoot间对版本有强制要求&#xff0c;我使用的springboot是3.0.2的版本。版本对应关系请看&#xff1a;版本说明 alibaba/spring-cloud-alibaba Wiki GitHub <dependency…

VSCode 加Cortex-Debug嵌入式调试方法

简介 当使用ARM Cortex-M微控制器时&#xff0c;Cortex-Debug是一个Visual Studio Code的扩展&#xff0c;以简化调试过程。本文档介绍了如何编写启动配置(launch.json)。 settings.json配置 打开VSCode用户设置文件settings.json: 文件→偏好→设置选择用户设置: 在搜索栏中…

(windows2012共享文件夹和防火墙设置

windows2012共享文件夹和防火墙设置 1.windows2012文件夹共享1.共享和高级共享的区别![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0d815cc6862a4c7a99be11442fb5d950.png#pic_center) 2.windows的防火墙设置1.防火墙设置8080端口让tomot可以在主机可以访问1.新建…

中间件系列 - Redis入门到实战(高级篇-最佳实践)

前言 学习视频&#xff1a; 黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目中间件系列 - Redis入门到实战本内容仅用于个人学习笔记&#xff0c;如有侵扰&#xff0c;联系删除学习目标 Redis键值设计批处理优化服…

电商数据分析-03-电商数据采集

参考 最最最全数据仓库建设指南&#xff0c;速速收藏&#xff01;&#xff01; 第1章 数据仓库概念 数据仓库规划 1.1 数仓搭建 我们这里所说的数据仓库&#xff0c;是基于大数据体系的&#xff0c;里面包含标签类目&#xff0c;区别于传统的数据仓库。下面我们来将这张图分解…

Java中的单元测试

单元测试 单元测试概述: 单元测试是指在软件开发中对软件的最小可测试单元进行测试和验证的过程。最小可测试单元通常是指函数、方法或者类&#xff0c;单元测试可以保证开发人员的代码正确性&#xff0c;同时也方便后期维护和修改。单元测试的主要目的是检测代码的正确性&am…

STM32 支持IAP的bootloader开发,使用串口通过Ymodem协议传输固件

资料下载: https://download.csdn.net/download/vvoennvv/88658447 一、概述 关于IAP的原理和Ymodem协议&#xff0c;本文不做任何论述&#xff0c;本文只论述bootloader如何使用串口通过Ymodem协议接收升级程序并进行IAP升级&#xff0c;以及bootloader和主程序两个工程的配置…

dxbuilder关于开发一款国产数据库建模软件的思考与行动

一、背景 随着一声紧急的呼叫&#xff0c;快快快。把你们有安装PownerDesigner的软件都卸载掉&#xff0c;公司被发律师函了&#xff0c;这是来自于领导的呼喊。 我们公司大部分的软件的数据结构&#xff0c;都是用PownerDesigner来进行设计的。以便进行后期的管理与维护。不…

前端面试题html

HTML DOCTYPE有什么作用&#xff1f; DOCTYPE是一种指示浏览器以何种HTML或XHTML规范来解析文档的声明。它能够告知浏览器网页文档使用的标记语言的类型以及版本&#xff0c;从而确保浏览器能够正确地展示网页内容。DOCTYPE声明通常位于HTML文档的开头&#xff0c;是HTML文档…

Vue学习之第一、二章——Vue核心与组件化编程

第一章. Vue核心 1.1 Vue简介 1.1.1 官网 英文官网: https://vuejs.org/中文官网: https://cn.vuejs.org/ 1.1.2 Vue特点 遵循 MVVM 模式编码简洁, 体积小, 运行效率高, 适合移动/PC 端开发它本身只关注 UI, 也可以引入其它第三方库开发项目 1.2 初始Vue 这里可以参考&a…

31--设计模式、面向对象设计原则

1、设计模式 1.1 设计模式概述 设计模式&#xff08;Design pattern&#xff09;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 设计模式不是一种方法和技术&#xff0c;而…

自定义删除无依赖文件的webpack插件

插件原理 通过自定义webpack插件&#xff0c;利用执行完成编译的封存阶段后&#xff0c;产生的产物module.fileDependencies&#xff0c;生成依赖的文件组。通过读文件的方式&#xff0c;将待扫描的文件组和有依赖关系的文件进行对比。最终暴露出项目中&#xff0c;不存在依赖…

ios 之 数据库、地理位置、应用内跳转、推送、制作静态库、CoreData

第一节&#xff1a;数据库 常见的API SQLite提供了一系列的API函数&#xff0c;用于执行各种数据库相关的操作。以下是一些常用的SQLite API函数及其简要说明&#xff1a;1. sqlite3_initialize:- 初始化SQLite库。通常在开始使用SQLite之前调用&#xff0c;但如果没有调用&a…

“京东”数据包暴雷——李逵还是李鬼?

大家好&#xff0c;我是吴军&#xff0c;一家软件技术开发公司的产品经理。 前几个月市面上出现了一个京东数据包的项目&#xff0c;乍一听还蛮正规的&#xff0c;强子不卖货&#xff0c;去做数据服务了&#xff1f;他究竟是怎么一个盈利方式&#xff1f;到底是李逵还是李鬼&a…

【新资讯】《网络安全事件报告管理办法(征求意见稿)》正在公开征求意见

近年来网络安全事故频发&#xff0c;造成了不少损失和危害。为了减少网络安全事故的发生&#xff0c;规范网络安全事件的报告&#xff0c;国家互联网信息办公室根据《中华人民共和国网络安全法》等法律法规起草了《网络安全事件报告管理办法&#xff08;征求意见稿&#xff09;…

释放创意,点亮视频!红巨星Magic Bullet Looks带给您绚丽的色彩魔法

Red Giant Magic Bullet Looks 是一款适用于Mac的视频后期处理软件。它是由Red Giant公司开发的一款专业级颜色校正和调色工具&#xff0c;旨在帮助电影制作人、视频编辑和摄影师实现令人惊叹的视觉效果。 Magic Bullet Looks 提供了一个直观而强大的用户界面&#xff0c;使用…

Linux操作系统(Crontab计划任务+NTP时间同步服务器)

如何修改linux系统时间 与时间相关的命令&#xff0c;查看当前的时间 运行 date 即可 cal 查看当前月份的日历 运行 timedatectl 查看时间详细参数 &#xff08; NTP&#xff1a; network time protocol 网络时间协议 &#xff09; &#xff08; local time : 本地时间 &#x…

volatile关键字详解

volatile 关键字详解 介绍 Java中的volatile关键字是一个用于确保变量在多线程环境下的可见性和部分有序性的修饰符。当一个字段被声明为volatile时&#xff0c;它具有以下特性&#xff1a; 可见性&#xff1a;在多线程环境中&#xff0c;一个线程修改了一个volatile变量的值…

采用curl -w测试接口或域名访问速度

命令&#xff1a; curl -o /dev/null -H "Cache-Control: no-cache" -s -w time_namelookup:"\t"%{time_namelookup}"\n"time_connect:"\t\t"%{time_connect}"\n"time_pretransfer:"\t"%{time_pretransfer}&quo…

BP算法与淋浴器的温度调节

BP算法&#xff08;反向传播算法&#xff09;是一种用于神经网络训练的基本算法。它通过逐层迭代地调整神经网络的权重和偏置&#xff0c;以使网络的输出尽可能接近期望的输出。BP算法之所以能够训练神经网络&#xff0c;是因为它基于梯度下降的思想&#xff0c;通过最小化损失…