多态与O2



数字在内存中都是以补码的方式存储的
为何这样,因为这样 正负数可以方便计算。
符号位和数据位
int_32  4个字节,第一位是0/1表示正/负,后面的2^31都是数据位,因此最大的正数是


正数的补码还是自己
负数的补码等于 符号位不变,数据位逐位取反然后加一,
相加就是补码相加 然后回到原码
相减就是加负数,变为补码 相加,然后回到原码。


编译时多态和运行时多态
重载起始就是编译时候存储不同的函数,完全不同的。
虚函数,虚指针实现运行时多态


class A;只是声明class,有什么成员还不知道,成员是没法访问的。
include则是把头文件也就是完整的class A的定义拿了过来,因此可以使用成员函数和成员变量




每个对象占用的存储空间只是该对象的数据部分(虚函数指针和虚基类指针也属于数据部分)
这是这些所占用的存储空间。而不包括函数代码所占用的存储空间


  对象1 对象2 对象3
—————— —————— ——————
| 数据 1   | | 数据 2   | | 数据 3   |
—————— —————— ——————
——————————————————————————————
| 公用函数代码 |
——————————————————————————————




成员变量
子类和父类没有同名的,那就不会出现任何的覆盖,
同名,但是virtual修饰了。那就覆盖
同名也米有修饰。如果是用父类类型,那么访问父类的,如果使用子类类型那么使用子类的


为啥。因为编译器会根据类型的不同取不同的偏移量。实际对象的地址是一样的,
只是指针类型编译器取偏移量不同。 做到了根据 不同的声明类型取到不同的 函数(常规函数 不是虚函数)


成员变量,虚函数表都是存在对象的内存空间的,但是非虚的成员函数则不是,
有专门的代码区来存储,也就是说同一个类,不同对象,他们的非虚成员函数的地址是一样的
所以根据指针类型访问函数,编译器会根据类型去取,
即使指向的类型不是自己的类型,比如
父类型指针指向子类对象,访问子类型中的非虚函数会编译错误
但是子类型的指针指向父对象,却可以访问子的非虚函数,
哪怕一个空对象,声明一个子类型的指针指向他,依然可以访问子类型的非虚函数。
因为编译器如此。偏移量


注意,子类和父类 同名的函数,同名的变量,隐藏。实际是两个东西,两个内存空间


结论:
定义一个父类对象,将该父类对象的指针强制转换为子类指针
并赋给一个子类指针
则该 子类指针将指向该父类对象,但是this指针已经变为声明的类型也就是 子类型的指针


当该指针调用虚成员函数,那么当然掉的是父类的虚成员函数(按照对象的内存布局
指向虚函数表的指针存储在该对象的前四个字节),对象里面存的不是虚函数表和变量
而是虚函数表的地址(四字节大小的指针)和变量
当该指针调用普通成员函数(非虚),将通过this指针的类型调用响应的函数
因为类型是子类,因此调用的同名函数就是位于代码段的子类的成员函数 虽然实际对象是父类


取虚函数看实际对象类型,虚函数表可以做到多态
取普通函数,声明什么,就访问什么




常量传播 常量折叠
-O -O1:
这两个命令的效果是一样的,目的都是在不影响编译速度的前提下,
尽量采用一些优化算法降低代码大小和可执行代码的运行速度。并开启如下的优化选项
-O2:
该优化选项会牺牲部分编译速度,除了执行-O1所执行的所有优化之外,
还会采用几乎所有的目标配置支持的优化算法,用以提高目标代码的运行速度
-O3:
该选项除了执行-O2所有的优化选项之外,一般都是采取很多向量化算法,
提高代码的并行执行程度,利用现代CPU中的流水线,Cache等。


编译优化,直接把可以计算的变量 用常量代替。O2优化会尝试使用常量替换变量
常量的好处生成立即数寻址的目标代码,常量作为立即数成为指令的一部分,减少内存的访问次数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值