探究c++对象模型之写在前面

第一章.关于对象


前言

c语言中数据和处理是分开声明的,也就是说语言本身没有支持数据和处理的关联性,我们把这种程序方法称为程序性。

而有一组以功能为向导的函数所驱动,共同处理共同的外部数据,这种称为对象性。


对象与成本

关于c++的对象,有人说由程序性到对象会增加成本,我们看看是否真的是这样的:

先考虑对于一个拥有成员变量的类,这个并没有增加成本。然后当类中增加了类成员函数,对于类成员函数,类成员函数虽然包含在类声明中,但是不属于对象。关乎类成员函数中有一个inline,当类成员函数被标记为内联,在每一个对象调用内联函数都会产生一个函数实例,这么做提高了效率,这个并不是成本的增加。

真正影响成本的是由virtual引起的:

Virtual function机制,用以支持一个有效率的“执行期绑定”。

Virtual base class用以实现“用以实现多次出现在继承体系的base class,有一个单一而共享的实例”。


c++的对象模式

 

简单对象模型:

 

目的:尽量减轻c++编译器设计的复杂度而开发出来的,赔上的是空间和执行期的效率。

实现原理:由一张指针表组成,所有指针都指向对象成员。

应用:c++指向成员的指针。


表驱动对象模型:


目的:为了使class所以的对象具有一致性。

实现原理:产生两个指针,一个指向data number table和一个 number function table

应用:虚表。


c++对象模型:


每一个class产生出一堆指向virtual function的指针,放在表格里,称为虚表。

每一个class object被安插一个指针,指向相关的虚表。虚表的设定交由构造函数,每个类关联的 type_info object也存放在虚表之中,通常放在表格的第一个slot

 

//其实关于多继承还是蛮复杂的

 

当多继承出现时,布局可能是这样的:

每一个derived class object内的一个slot指出base class的地址。

优点是对象不会因为base class的改变而影响。

缺点是由于间接性而导致的空间和存储时间上的额外负担。

 

构造函数的语义学

 


defaultconstructor的构造操作

 

c++标准说:当用户未曾创建构造函数时,编译器会提供给用户一个trivialconstructor

 

那么什么时候会提供呢?

当编译器需要一个constructor的时候。

 

一共有四种情况:

  1. 当一个类中包含class object number,并且这个class object number含有一个 default constructor
  2. 当一个类含有base class的时候,并且这个 base class 具有default costructor的时候。
  3. 当一个类具有virtual function的时候。
  4. 当一个类是以virtual继承的方式继承的时候。

 

Copy constructor的构造操作

其实关于default constructor我都知道做了些什么,关于这个copy,我们会在哪里用到它呢?

  1. 拷贝构造
  2. 函数的值传递和函数的返回值构造。

Copyconstructor的内部构造方式:

把每一个内建的data member的值拷贝一份给另一个object,如果data member也是一个类,则递归,这个叫memberwiseinitialzation。(成员逐次初始化?)

 

而实际上Arm告诉我们说,概念上这,对于一个classX这个操作是由copy constructor实现的。而实际上一个良好的编译器可以为大部分class object产生bitwrist copy ,因为他们是具有bitwrist copy语义的。


那么什么叫bitwrist copy呢?位逐次拷贝。

 

我发现位逐次拷贝和我们所说的浅拷贝差不多,但是真的差不多么?我们一会再看

 

我们先说一下什么时候不会展现bitwristcopy,而由编译器为你创建一个copy construct

1.当一个类中含有类对象,而这个类对象中含有copy construct的时候。

2.base class中含有一个copyconstruct中的时候。

3.class中含有virtualfunction的时候。(因为虚表的创建是由三大构造函数指明的。这里没算上移动构造函数)

4.class派生自一个继承串,而其中有一个或多个virtual base class 的时候。(这种情况和其他三种不太一样,因为其他都发生平行赋值就会引发copy construct(也就是说类对象与类对象之间的),而第四种是发生在派生类与父类之间的赋值才会体现,因为virtual base class 是动态的,由于各个编译器实现不同我们可能会改变offset或者其他如virtualbase class 的位置啊,什么的?这完全取决于编译器实现,但是,一定会引发copy construct的产生是毋庸置疑的)

 

浅拷贝bitwrist copy

浅拷贝与bitwrist copy并不是一个东西,浅拷贝主要是用来说明在类成员中存在指针的情况下,浅拷贝会造成的种种原因的一个表象说法,而关于bitwrist copy用来针对与copyconstructor的一个大范围的一种copymeathod

 

关于bitwrist copymemberwristcopy的关系,我还有一点自己的理解就是memberwristcopy是依赖bitwrist copy的,对于基本类型我们只能通过bitwrist copy,因为基本类型没有copy constructor

 

对于memberwrist copybitwristcopy,我看到的第一个想法就是关于内存泄漏方面,事实上来说,有点关系,只不过这个是专门用来描述对象模型的,对于内存泄漏会有一定帮助但是帮助不大。


程序转化语义学

 

这一章讲了,编译器为我们做了什么,使得我们在编写程序的时候“得心应手”,与编译器的优化。

 

 

显示初始化操作:

 

我们在显示初始初始化的时候是如何书写的,如下:

 

已知:
X x0;
则
X x1(x0);
 
这段代码被程序转化成什么样呢?
 
1.x1被重新定义,剥夺其初始化操作:
X x1;
2.调用X的copy construct
x1.X::X(x0);


 

参数的初始化:

 

当我们在传参的时候直接通过在参数内构造临时对象时,也会分为两个步骤:

1.将构造方法与函数调用剥离,构造一个临时对象。

2.将临时对象传入函数。

 

也就是说我们会依次调用两个构造函数,所以会造成什么后果你懂的。

 

但是有的编译器会把实际参数直接构建在应该的位置上。也就说我们少构建一次。

 

返回值的初始化:

 

对于一个X bar();

 

优化方式如下:增加一个额外参数,类型为class object的一个引用(X&,在返回指令前安插一个copy construct从而获得返回值。

 

如下:

 

X bar();
 
 X vczh =bar();
 
 
伪代码
Voidbar(X& _result){
 
X x;
 
 _result.X::X(x);
Return;
}
 
 
  //剥夺初始化的权利
Xvczh;         
bar(vczh);

  

在使用者层面做优化:

 

这个没什么说的了,所谓使用者优化,就是垃圾程序员写的垃圾代码最后由编译器收拾烂摊子,收拾的好坏,能不能收拾,这个呵呵。

 

编译器层面做优化:


这里介绍了
Name Return Value (NRV)优化,我所理解的NRV优化就是省去代码中最后作为返回结果的临时对象,而通过返回值的初始化,直接对返回值进行修改。从而减少一次对象构造的机会。

 

我在想为什么NRV优化对于编译器这么重要,我们也可以写成像NRV优化出来一样的代码啊,我们也可以剥夺初始化的权利,引用调用,我觉得实际上,这个代码对于审阅的人来说太复杂了不是吗?他需要顺着你的思维去了解代码,要是猪队友怎么办?他不懂,那么糟糕了。我们在写代码的时候不要过分追求这些,有些东西底层帮你做了,那么你就负责写出能被编译器尽量优化的和能被队友审阅的代码,那么就ok了。

 

成员初始化列表


1.当初始化一个reference member时。

2.当初始化一个const member

3.当调用一个基类的构造函数的时候。

4.当调用一个member classconstructor,而他拥有一组参数的时候。

 

list中的项目顺序是由class中的member声明顺序决定的,不是由,initializationlist中的排列顺序觉定的。

List是先于函数体内构造的,所以为了防止编译器为我们在构造函数体内添加东西,我们应该在list中构造而不是选择在函数体内构造。

尽量不要在list使用类成员函数对类成员进行初始化,你不知道成员函数对类对象的依赖性有多高。

 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值