【C++对象模型】之Data Members

2024-05-12 06:38
文章标签 c++ 模型 对象 data members

本文主要是介绍【C++对象模型】之Data Members,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Data Member语义

C++将nonstatic data members直接放在每一个class object中。对于继承而来的nonstatic data members(不管是virtual或是nonvirtual base class)也是如此.

static data members被放置在程序的一个global data segment中,不会影响个别的class object的大小。在程序中,不管class被产生出多少个objects,static data members永远只有1份实体(甚至,即时该class没有object实体,其static data member也已经存在)。

Point3d origin;
Point3d &p;
origin.x = 0.0;
p->x = 0.0;//问题:通过origin和p存取x,开销有什么区别?从classdata member的角度来分析。

​ 首先,要区分x是static还是nonstatic。如果是static,那么不管是origin还是p,他们是没有任何区别的。因为static data member是放在data segment中,不同class的如果有名称冲突,就用name mangling来解决。

​ 其次,如果x是nonstatic data member。在编译时期,会把nonstatic data member直接复制到子类中,所以他的偏移量是已经确定了的。不管是class本身就有的,还是继承来的(包括多重继承)。但是,如果data member是从virtual base class继承来的,那么就会慢一些,因为通过指针我们无法确定p到底指向的是谁,所以要到执行期才能确定。而Point3d origin,就一定是一个Point3d所以data member的偏移量在编译时就确定了。

继承 与 Data Member

  • base class subobject 在 derived class中原样性,指的是出现在derived class中的base class subject有其完整的原样性。这里就包括了内存对其的情况,也就是说为了抽象化,会使得derived class所占的空间变大。

1.单一继承且不含virtual function

  • 由于继承保证的原样性,导致子类空间可能会变大。主要是因为父类有内存对其的行为,子类必须把padding也复制过来,否则就破坏了原样性。

2.单一继承且含有virtual function

为了支持多态,增加了virtual function,必然带来空间和存取时间的额外负担,主要表现如下:

  • 生成一个Virtual table,用来存放它所声明的每一个virtual function地址。table元素的数据一般是被声明的virtual function的数目再加上一两个slots(用来支持runtime type identification)。
  • 在每一个class object中导入一个vptr,提供执行期的链接,使每一个object能够找到相应的virtual table。
  • 加强constructor,使它能够为vptr设定初值,让它指向class所对应的virtual table。这可能以为这在derved class和每一个base class的constructor中,重新设定vptr的值。
  • 加强destructor,使它能够抹消“指向class之相关virtual table”的vptr。要知道,vptr很可能在derived class destructor中被设定为derived class的virtual table地址。而且,destructor的调用次序是反的。

3.多重继承

​ 多重继承,按照声明的顺序,从上到下依次排列 subobject。所以,无论是存取哪一个的data member,都不需要付出额外的成本。members的位置在编译的时候就固定了,因此存取members只是一个简单的offset运算,就像单一继承一样简单—-不管是经由一个指针、一个reference或是一个object来存取。

4.虚拟继承

总体思路就是把数据分为固定部分和共享部分。固定部分直接放到前面,不在变化。共享部分就是virtual base class的部分,有两种处理办法,分别对应两种内存布局。

  • 在每一个子类中安插一个指针,指向virtual base class。 固定部分全都都放在最前面,然后放置一个指针指向virtual base class,然后放置vptr。

  • 在每一个子类的virtual table开头处,记录下virtual base class相对于当前subobject的offset。省去了每个指针的所占的内存大小。

指向Data Member的指针

区分& Point3d::x 和 & origin.x:

  1. 取一个nonstatic data member的地址,将会得到它在class中的offset。 &Point3d::x
  2. 绑定于真正class object身上的data member的地址,将会得到该member在内存中的真正地址。 & origin.x

为了区分一个没有指向任何data member的指针,和一个指向第一个data member的指针,所以每一个真正的member offset值都被加上一。

float Point3d::*p1 = 0;
float Point3d::*p2 = &Point3d::x;    
if ( p1 == p2)
{cout << "p1 p2 contain the same value -- they must address the same member " << endl;
}
// 这个是可以区分的,因为就算x在第一个,他的offset也被加了1. 也就是说 &Point3d::x表示取x的offset,而offset都是真实的offset+1。

这篇关于【C++对象模型】之Data Members的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/981877

相关文章

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre