Effective C++ 阅读笔记(二)

《Effective C++》 读书笔记(详细总结55条款)上篇 下面从四个方面来说 (1) C++ 以 C 为基础,很多语句语法都没有改变,只是进行了扩展,C++ 解决问题的时候,可以理解为 C 的高效解法 (2) 面向对象,有构造函数,析构函数,继承、封装、多态、虚函数动态绑定,这是不同于C 语言的部分 (3) 泛型编程、可以理解为代码的模型,但是代码本身并不占用内存空间,只有在实例化的时候,才分配内存,所以可以提高代码复用性 阅读详情

05:了解C++默认编写、调用的函数

  • 如果没声明,编译器会声明一个copy构造函数,一个copy assignment操作符,和一个析构函数;如果没有声明任何构造函数,编译器也会声明要给default构造函数。
  • 包含reference和const成员的class,编译器会拒绝自动编写assignment操作;如果base classes将copy assignment声明为private,编译器将拒绝为derived classes生成copy assignment函数。

06:如果不想使用编译器自动生成的函数、那就明确拒绝

建立新类:

class Uncopyable {
	protected:
		Uncopyable() {} //允许子类构造和析构
		~Uncopyable() {}
	private:
		Uncopyable(const Uncopyable&); //阻止拷贝
		Uncopyable& operator=(const Uncopyable&);
};

然后新类就继承这个类。

其实新标准里面可以使用=delete来进行禁止。

07:为多态基类声明virtual函数

  • polymorphic(带有多态性质的) base classes 应该声明一个 virtual 析构函数。如果 class 带有任何 virtual 析构函数,那他就应该拥有一个 virtual 析构函数。
  • classes 设计的目的如果不是作为 base classes 使用,或者不是为了具备多态性(polymorphically),就不该声明为 virtual 函数

原因是,如果基类虚构函数是 non-virtual 的,那么 derived class 由 base 指针删除时,可能 derived 成分,也就是 derived class 中新声明的变量无法被正确析构。

而声明为析构函数会使得对象占用额外的空间用来保存函数指针。

08:别让异常逃离析构函数

  • 析构函数不应该抛出异常。如果一个析构函数调用的函数可能抛出异常,析构函数应该捕获任何异常,然后吞下他们(不传播)或者结束程序。
  • 如果用户需要对某个操作函数期间抛出的异常做出反应,那么 class 应该提供一个普通函数(而非在析构函数中)执行该操作。

比如读取文件操作,最后需要关闭文件。一个较好的的做法可以是:

class FileManager {
	bool isClosed;
	public:
		...
		void close () {
			file.close();
			isClosed = true;
		};
		
		~ FileManager() {
			if (!closed) {
				try {
					file.close();
				} catch (...) {
					//记录对close调用失败,吞下异常或者结束程序
				}
			}
			...
		}
};

可以让用户处理关闭操作,并进行异常捕获,如果没有进行操作,默认提供一个,如果出现了异常,就吞下或者结束程序。

09:不在构造和析构过程中调用virtual函数

  • 不要在析构或构造期间调用 virtual 函数,因为他们不会下降到 derived class,而是在构造啥类型期间,就调用啥类型的 virtual 函数。

在 derived class 的 base class 构造过程中,对象的类型是 base class,并且不仅 virtual 函数会被编译器解析到(resolve to) base class,运行期间的类型信息(runtime type infomation, e.g. dynamic_cast, typeid)也会把对象当作base class。

析构的时候也是这样,一旦 derived class 析构函数执行,对象内的 derived class 成员变量变成先未定义值,进入 base class 之后就变成一个 base class 对象。

但是,如果想要每一个 derived class 被创建时,都有适当的一些信息被输出,要怎么做呢?可以在 base class 内创建一个 non-virtual function,并在构造函数中调用这个函数;derived class 在构造时,将必要的信息传给这个基类的构造函数。

class BaseClass {
	public:
		BaseClass(string& info) {
			...
			printLogInfo();
		}
		
		void printLogInfo(string info} {...}
};

class DerivedClass : public BaseClass {
	public DerivedClass(param) : BaseClass(createInfo(param)) {...}
	string createInfo(parm) {...}
}

10:令operator= 返回一个reference to * this

令赋值操作(assignment) (=, += ,-=, *=)返回一个 reference to *this。

为了实现类似:

int x, y, z;
x = y = z = 15;

之类的连锁赋值。

11:在operator= 中处理自我赋值

  • 确保对象自我赋值时,operator = 有良好的行为。其中计数包括
    • 比较“来源对象”和“目标对象”的地址
    • 精心周到的语句顺序
    • copy-and-swap
  • 确定任何函数如果操作一个以上的对象,其中多个对象是同一个对象时,行为仍然正确

比如有一个类:

class A {
	public:
		A(B& b) { pb = &b; }
	private:
		B* pb;
	...
}

使用下面的 operator= 代码,看上去很合理,但是自我赋值会出现问题:

A& A::operator=(const B& rhs) {
	delete pb;
	pb = new A(*rhs.pb);
	return *this;
}

这时,如果当前对象传入的对象是同一个对象,那么当程序执行完之后,rhs就指向了一块被删除的地址。

一个想法是,在最前面加一个“证同测试(identity test)”来达到“自我赋值”的检验

A& A::operator=(const B& rhs) {
	if (this == &rhs) return *this;
	
	delete pb;
	pb = new A(*rhs.pb);
	return *this;
}

但这样并不具备异常安全性,同时效率比较低

  • 如果new时,内存不足,或者拷贝构造函数出现异常,那么pb都会指向一块被删除的地址
  • if 语句会使程序更大,并且引入一个新的控制流分支,二者都会降低速度。Perfectching, caching 和 pipelining 等指令的效率都会因此降低。

精心安排一下语句的顺序,可以解决异常安全问题:

A& A::operator=(const B& rhs) {
	auto tempPb = pb;
	pb = new A(*rhs.pb);
	delete pb;
	return *this;
}

这是,如果 new 语句发生异常,两个变量中的pb仍然会保持原状。

一个替代方案是 copy and swap技术:

class A {
	...
	void swap(A& rhs); // 交换*this 和 rhs 的函数
	...
}

A& A::operator=(const B& rhs) {
	A temp(rhs);
	swap(temp);
	return *this;
}

或者是:

A& A::operator=(const B rhs) {
	swap(rhs);
	return *this;
}

这种写法利用了两个技术:

  • 某 class 的 copy assignment 操作符可以被声明为“以 by value 方式接受实参”
  • by value 方式会造成一份副本

这种方式牺牲了清晰性,不过将 copying动作 从函数本体移动到 函数参数构造阶段 有时可能会令编译器产生更高效的代码。

12:赋值对象时勿忘其中每一个成分

  • copying 函数应该确保赋值“对象内所有成员变量”以及“所有base class”成分
  • 不要尝试以某个 copying 函数实现另一个 copying 函数,应该将共同的技能放在第三方函数中,并且由两个 copying 函数共同调用。
2、瑞丽-伯纳德对流的拉格朗日拟序结构(FTLE场结果对比) 在中,我简单比较了瑞丽伯纳德对流的FTLE场,但是因为粒子追踪采用的是欧拉方法,所以精度不是很高, 因此与文献中的结果还是有些差别。下面放一张文献中的FTLE场,参数与上篇文章是一致的,Ra = 1e8;Pr = 1;本文将详细的介绍如何得到这样的图片,好吧,其实也不是很详细。总之,先展示以下我个人的结果。可以看出,上图基本上与文献是一致的,因为这里展示的是瞬时场,所以当然不可能是完全一致,至于提取的LCS结构,我在下面也会提及。本着详细介绍的原则,所以这里我很良心的从流场计算开始介绍。 阅读详情

相关推荐

Windows Server 2012 R2虚拟机安装全攻略:从镜像选择到网络配置一步到位

本文提供Windows Server 2012 R2虚拟机安装全攻略,涵盖从镜像选择到网络配置的完整流程。详细讲解在Oracle VM VirtualBox中的安装步骤、TCP/IP网络设置、系统优化及常见问题解决方案,帮助用户快速搭建可立即投入使用的服务器环境。特别适合IT初学者和系统管理员学习传统服务器应用的部署与配置。

weixin_28363123的博客 538

《Effective C++》 总结笔记

1. 让自己习惯C++ 1:视C++为一个语言联邦 c++是多重范型编程语言,视c++包括4种次语言: 1:C; 2:Object-Oreinted C++;3:Template C++;4:STL(template程序库,包括容器、迭代器、算法和函数对象)。 2:尽量以const,enum,inline替换 #define const: #define直接替换导致名称从未被编译...

stIck_NHNP的博客 8707

05-SA8155 QNX Display框架及代码分析(1)

显示是非常重要的一个模块,人机交互的桥梁。那么SA8155 Hypervisor显示是如何处理的呢。对处理流程非常的好奇O(∩_∩)O哈哈~。TODO。

静虚待令,有物混成 1万+

Effective C++阅读笔记 二

1,了解C++编译器默认编写的函数 对于一个类,编译器会根据需要创建默认构造函数,默认拷贝函数,默认析构函数以及默认重载赋值运算符。但值得注意的是,只有这些函数需要被调用并且我们没有手动定义的时候,它们才会被编译器创建。 值得注意的是,对于拷贝构造函数或者赋值运算符的重载,由于默认的只是简单的赋值,所以对于成员变量为const的情况下,编译器也不会生成对应的默认函数。甚至在我测试的C++14中,如果存在const成员变量,编译器会拒绝生成默认构造函数。(不一定正确) ...

Sputnik_02的博客 196

CUDA系列-Stream-1

This section describes static aspects of the CUSW_UNIT_STREAM unit’s architecture.和stream相关的其它Unit主要有Channel,Sync,Memmgr A CUDA stream is a software FIFO queue that allows commands like kernel launch and memcpy to be enqueued in it. The enqueued commands

weixin_43360707的博客 734

5G/NR SSB学习总结

6.1 SSB概念 同步信号和PBCH块(Synchronization Signal and PBCH block, 简称SSB),它由主同步信号(Primary Synchronization Signals, 简称PSS)、辅同步信号(Secondary Synchronization Signals, 简称SSS)、PBCH三部分共同组成。 6.2 SSB特征 ...

欢迎来到小七的博客,这里将带你深入探索5G通信的神秘世界。无论你是通信领域的专业人士还是对这一领域充满好奇心的技术爱好者,这里都有专业协议解读、通信知识普及以及有趣的Python编程内容等你发现。 8万+

Effective C++阅读笔记②

三、资源管理 Resource Management 13:以对象管理资源 Use objects to manage resources 1、像auto_ptr、share_ptr那样管理对象 2、auto_ptr被销毁时会自动删除所指对象,所以不要让多个autp_ptr指向同一个对象。如果以copy构造函数或者copy_assignment操作符复制他们,他们会变为null,而复制所得的新的指针或获得资源的唯一拥有权。STL容器容不得auto_ptr。 3、share_ptr属于RCSP(referen

weixin_45680994的博客 140

【嵌入式DIY实例-Arduino篇】-脉搏传感器监测脉搏率 (BPM)及可视化

在本文中,我们将使用 Arduino 和脉搏传感器来测量心率 (BPM)。 在文章中,我们将向展示如何使用脉搏传感器测量您的心率(每分钟心跳次数),并在电脑上位机通过Processing来实现心率数据可视化。同时使用LCD16×2 显示屏显示脉搏率 BPM。 该传感器易于使用和操作。 只需将手指放在传感器顶部,它就会测量心跳变化。

视觉与物联智能 834

Effective C++阅读笔记(二)

目录 目录 条款18-25——设计与声明 条款26-31——实现 条款32-40——继承与面向对象设计 条款18-25——设计与声明 条款18:让接口容易被正确使用,不易被误用 好的接口应当被正确使用,不容易被误用。 促进正确使用的办法:接口的一致性、内置类型行为兼容。 阻止误用的办法:建立新类型(如在日期类中加入年月日类封装数据以避免非法数据)...

宗越的博客 323

[系统安全] 一.什么是逆向分析、逆向分析基础及经典扫雷游戏逆向

娜璋AI安全之家于2020年8月18日开通,将专注于Python和安全技术,主要分享Web渗透、系统安全、CVE复现、威胁情报分析、人工智能、大数据分析、恶意代码检测等文章。真心想把自己近十年的所学所做所感分享出来,与大家一起进步。 系统安全系列作者将深入研究恶意样本分析、逆向分析、攻防实战等,通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步。第一篇文章先带领大家学习什么是逆向分析,然后详细讲解逆向分析的典型应用,接着通过OllyDbg工具逆向分析经典的游戏扫雷,再通过Cheat Engin

杨秀璋的专栏 2万+

YOLO11涨点优化:注意力魔改 | 引入Deformable Attention (可变形注意力),灵活感受野自适应复杂形变目标

Deformable Attention为YOLO11带来的不仅是2.6个百分点的mAP提升,更是一种全新的“形变感知”范式。标准卷积的固定感受野在非刚性目标、多尺度变化和遮挡场景下力不从心——Deformable Attention恰好填补了这一空白。从架构设计到代码实现,从竞品对比到部署方案,从生态工具到安全风险,本文覆盖了将Deformable Attention引入YOLO11所需的全部知识链路。

2601_95807009的博客 286

《Effective c++》阅读笔记二:让自己习惯于C++

对大多数

沉墨笙箫的专栏 634

WOFOST作物模型(7):6.0.6版本的PCSE使用(多层水分平衡和SNOMIN碳氮模型的集成)

wofost81文件结构如上,其中所需的参数可从github上获取然后input下有两个需要调用的功能函数py文件,需要拖到自己的运行py文件同级目录下在使用土壤模块SNOMIN进行作物生长模型模拟时,需要为土壤剖面的不同层次提供多种输入变量。这些变量通常不随年份变化,因此会统一在土壤文件中定义。本节将说明如何将这些输入变量整合到一个字典中,进而生成SNOMIN能够读取的土壤文件。

所有专家都曾始于新手 638

More effective C++阅读整理笔记(条款一、二、三)

More effective C++阅读整理笔记

qq_41916893的博客 321

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Effective C++ 阅读笔记(二)public继承与继承中的函数覆盖

 public继承是一种is-a关系。也就是说适用于base classes(基类)身上的每一件事都一定适用于derived classes(继承类),每一个derived classes对象都是一个derived classes对象。 class A{ void func(); ... } class B : public A{ ...

weixin_34004576的博客 102

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

More Effective C++ 阅读笔记(二) -- C++的新型类型转换(造型Cast)

 More Effective C++ 阅读笔记(二) --  C++的新型类型转换(造型Cast)黑月亮 发表于 2005-10-1 21:57:00    C++的新型类型转换(造型Cast)C++的新型类型转换共有四种方法代替传统的C造型(即(type)expression)这四个操作符是, static_cast, const_cast, dynamic_cast, 和rein

699

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Effective C++ 阅读笔记(二)透彻了解inline以及降低编译依存关系

  public继承是一种is-a关系。也就是说适用于base classes(基类)身上的每一件事都一定适用于derived classes(继承类),每一个derived classes对象都是一个derived classes对象。 class A{ void func(); ... } class B : public A...

weixin_34096182的博客 113

《effective C++》阅读笔记

《effective C++》阅读笔记

subtitle_的博客 1046

【C++】万字详解Effective C++

本文为前段时间读《Effective C++》(侯捷译)时做的个人笔记。

Friday 4293

Effective C++阅读笔记(一)

0. 导读学习程序语言根本大法是一回事;学习如何以某种语言设计并实现高效程序设计是另一回事。 术语: 声明式(Declaration):告诉编译器某个东西的名称和类型,但略去细节。 签名式(Dignature):(函数)参数和返回类型。 定义式(Definition):提供编译器一些声明式所遗漏的细节。 初始化(Initialization):给予对象初值的过程。 对象初始化:default构造

X@IAS 1020

Effective Modern C++阅读笔记

charstrerror(interrnum)接收一个错误码,返回错误信息s)先打印字符串s,再根据当前errno打印信息。

yao-xin 1034

Effective C++读书笔记

前些天看了《Effective C++》这本书,感受颇深,现将读书过程中记录的相关笔记总结如下,希望会对大家有所帮助。 1、千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用。     原因:返回一个局部对象的引用他的问题在于,局部对象仅仅是局部的,也就是说局部对象是在定义时被创建,在离开生命空间时被销毁的。所谓生命空间就是他们所在的函数体,当函数返回时,程序的控制离

Silence723的博客 653

Effective C++阅读笔记(item 1-4)

我们回到最开始说的*p的情况,p是一个单纯变量名,如果decltype§返回的是p的声明类型,然而*p是返回左值的复杂表达式了,因此decltype返回的是左值引用,类型是表达式的类型。传递一个临时变量也并不是没有意义,有时候用户可能只是想简单的获得临时容器中的一个元素的拷贝,比如这样)==,我们需要将声明改为通用引用(也可以重载函数)。忽略引用行在指向常量的常量指针情况下只会忽略底层const,这一特性只会对形参本身有效,因此指针的常量特定会被忽略,但是指针所指对象的常量特性会被保留。

顾若茵的博客 1084

Effective C++ 阅读笔记之Chapter1

前言 大家好,我是雨墨,我深知好记性不如烂笔头的道理,所以在阅读的时候都尽量写读书笔记,方便日后复习,当然笔记并不能代替书籍上的内容。希望我的笔记也能帮助到大家,如果我的笔记有什么问题,欢迎大家给小老弟纠错~ 条款一总结 视 C++ 为 C 、 面向对象、template、STL 的联邦 条款二总结 宏定义的坏处: 一方面以 #define example 17举例 编辑器调试的时候,很有可能会造成错误信息是17,然后让你不知所措,这是什么?从哪来的?。 预处理器可能盲目地将example替换成17,导

qq_51387669的博客 287

Effective C++读书笔记博客汇总

做过两个项目以后,第二次读才写的博客,有一些地方确实在项目中会运用到,但其他的还是有不少不太理解的,之后再做做别的项目进行第三次阅读之后再进行补充。我是第一次读到一半就没读了,觉得看不懂,读起来也比较枯燥。

m0_74795952的博客 767
上一篇: Effective C++阅读笔记(一)
下一篇: Effective C++ 阅读笔记(六)
Cross_Entropy
博客等级 码龄7年 69粉丝 45原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值