more effective c++ 读书笔记 第一章

more effective c++ 读书笔记 第一章 :基础议题

条款一
仔细区别pointers和references

区别指针和引用,没什么好说的,基础知识。不过有个有趣的问题,之前没有考虑过:

char *pc = 0;
char& ref = *pc

本质上,还是说对空指针、 野指针解引用,然后绑定到引用上,这样做,是未定义的。

条款二
使用c++类型转换符

这部分较为基础,值得注意的是,dynamic_cast 用于向下转型,如果指针转换失败,返回nullptr, 如果是引用,抛出异常。
另外,对于static_cast和reinterpret_cast 之间的深层次的区别,书中未提到,按照笔者的经验,优先static_cast,如果不行,编译器会报错,然后一般就需要reinterpre_cast,参考这里的解释:

https://stackoverflow.com/questions/6855686/what-is-the-difference-between-static-cast-and-reinterpret-cast

一般而言,static_cast是符合你的直觉的,如,int值转为float值,这是有意义的做法。而reintepret_cast,一般是较低级的转换,意思是对内存做某种重新解释,如,将int* 转为float*,解引用的话,这会将int的二进制表示解释为float值了,你根本猜不到这是什么值,此外, 对于void*的来回转化 ,是需要static_cast的,这其实也符合一般直觉的。

此外再讨论一个问题。就是类型转换做了什么。一般const_cast转换,不需要生成真正的代码,因为const是编译器级别的保护,const_cast只是告诉编译器,去掉保护。
对于static_cast, 大多应该是需要生成代码的,如

float f= 1.0;
int a = static_cast<int>(f);

这里需要生成代码,一般是某种寄存器操作,将float转为int值,然后写入a的内存
在这里插入图片描述
cvttss2si eax, xmm0
这条指令,就在做转型相关操作。

对于dynamic_cast,无须多言,使用了RTTI机制,显然需要生成额外代码。

对于reinterpret_cast,
在这里插入图片描述
观察到,这里没有额外代码,不过这也是符合逻辑的,因为,对于汇编语言或者cpu来说,没有类型之分,只是位宽有不一样,只是将一个地址值赋给另一快内存空间,但是static_cast需要生成转换后的值,所以需要生成额外代码来操作。
需要注意的是,对于派生类和基类的地址相互转换,地址空间的调整,要稍微复杂一下,尤其涉及到虚函数的类,此处可阅读 <<深度探索c++对象内存模型>>

条款三
不要以多态方式处理数组

书中主要举了两个例子
1:

class A {
int a;
};
class B : public A {
int b;
};
void Func(A* ap, int nums) {
	for (int i = 0; i < nums; i++) {
		doSomeThing(ap + i);
	}
}
B bArray[10];
Func(bArray, 10);

这样做是错的,由于多态的存在,将B指针传给Func,是OK的,但是在函数内部,指针递增时按照sizeof(A)递增, 这会导致未定以行为。
2:

void Delete(A ap[]) {
	delete [] ap;
}
Delete(the pointer of B)

这样做也是错的,因为对于delete [] array,编译器可能生成如下代码

for (int i =nums of array elements - 1; i >=0; i--) {
	array[i].A::~A;
}

显然,这里也涉及到用多态指针做递增操作,这会有和上面一样的问题。
不过这里需要多解释一下,基类指针指向派生类,然后delete这个基类指针,其实是常见操作,只是这个操作,不涉及数组,也就不涉及指针加减,这里重点讨论的,就是不要做多态指针的加减,这样是错的,不要混淆。
此外还有一点,如何知道delete 或free的地址空间大小呢,一般在地址 p 之前的4字节,也可能是8字节,会记录这块地址的大小,所以,上述的delete [] ap,其实会free这块一整地址空间(即B数组字节数) 比如m个字节,数组元素个数是 m / sizeof(A), 会比原来多(原来是m / sizeof(B)),上述示例的删除代码,其实不严谨。(这里参考的是侯捷老师的内存管理课程,如有错误,欢迎指正 : ~)。

条款四
非必要不提供default ctor

即默认不提供不带参数的构造函数,可能有点形而上学,作者写的篇幅不短,但是我get到的是,如果使用了defaylt ctro,那么可能需要成员函数每次使用前去检查一下状态,因为此时的内部变量,可能是一种无效值。anyway, that’s all。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值