精华内容
下载资源
问答
  • 请描述一下多重继承在内存中的存储模型 普通类在内存中的存储情况  VTAB(  Data 如果一个类有虚函数,那么它就有虚函数表,类的第一个单元是一个指针,指向这个虚函数...

    请描述一下多重继承在内存中的存储模型

    • 普通类在内存中的存储情况 

    VTAB(<- this)

     Data

      • 如果一个类有虚函数,那么它就有虚函数表,类的第一个单元是一个指针,指向这个虚函数表
      • 如果一个类没有虚函数,他的祖先(所有父类)均没有虚函数,那么它的内存映像和C语言里的结构一样
      • 如果类Y是是类X的一个继承(X是父类),那么类Y在内存中的结构如下

    YVTAB(<- this)

    Xdata

    Ydata

      • 现在看看class D多重继承
    class D : public A, public B, public C 
    
    { 
    
       .... 
    
    }
    
    
      • 有了这种多重继承关系之后,这几个类在内存中的存储结构如下,

    D的vTable(存的是一个指针)

    A的数据

    B的vTable(存的是一个指针)

    B的数据

    C的VTable(存的是一个指针)

    C的数据

    D的数据

      • 多重继承时,当把一个派生类强行转化成它的基类,它是能准确的找到他对应的虚函数表的。
      • 而通过这个多重继承中的某个基类,其实也能找到其对应的派生类的虚函数表(通过偏移)。
    展开全文
  • 尽管AMPAR的突触调节被认为是大脑信息存储的基础,尽管对此主题进行了大量研究,但AMPAR介导的突触可塑性仍存在不确定性。 但是,关于AMPAR贩运机制,有大量信息可用来开发突触可塑性的统一模型。 这样的模型可用于...
  • data member(数据成员),member function(成员函数),virtual member function(虚函数),以及在虚拟继承中,单继承,多重继承等各个角度,来探索C++类中的存储。 (申明,本文章中涉及的所有

    本文将继上篇文章,【C++】深度探索C++对象模型之虚拟成员函数(virtual member function), 

    继续探索C++类中,

    • data member(数据成员),
    • member function(成员函数),
    • virtual member function(虚函数),
    • 以及在虚拟继承中,单继承,多重继承等各个角度,来探索C++类中的存储。

    (申明,本文章中涉及的所有运行,运行环境为: Codeblocks 13.12

    一、数据成员,成员函数,以及虚函数内存占用问题

    首先通过以下一段源码,进行抛砖引玉
    class A {};
    
    class B{
    public:
        B(){}
        ~B() {}
    };
    
    class C{
    public:
        C() {}
        virtual ~C() {}
    };
    
    class D {
    public:
        D() {}
        ~D() {}
    
    private:
        int m_data;
        char c;
    };
    
    int main()
    {
        cout << "A = " << sizeof(A) << endl;
        cout << "B = " << sizeof(B) << endl;
        cout << "C = " << sizeof(C) << endl;
        cout << "D = " << sizeof(D) << endl;
        return 0;
    }
    
    上述代码中,运行的结果如下:

    运行结果分析:
    1、A是空类,大小为1,其中的主要理由是:空类并非空,它隐藏着1 byte的大小,由编译器安插进去的一个char,使得以这个类实例化的object,在内存中拥有独一无二的地址。
    2、B存在构造函数,以及析构函数。然而大小依旧为1。说明对象所占用的空间大小,与类成员函数无关。
    3、C的大小为4。首先,应该注意的是,1中所说的标志独一无二的1 byte char将被此时存在的数据成员而替代。也就是不再需要那个1 byte char来指示地址,因为类成员中本身就存在地址。 这C中的这个类成员,就是一个vptr, 指向类C的virtual table。所以sizeof(C)其实就是求出了类C中的指向virtual table 指针的大小。
    4、D进一步说明了,对象所占用的空间大小,与类成员函数无关,而与数据成员,虚函数的指针等有关。当然,这里的大小,需要进行补齐。因为原先的大小为 4 + 1, 但由于自动补齐,使得最终大小变成了 4 + 4。

    二、成员函数的存储方式

    首先,直观的是,用类去定义对象,系统将会为对象分配存储空间。如果一个类包含了数据成员和函数,那么就需要单独为数据和函数分配存储空间。
    所以,直观的感觉是,如果我们为一个类分配了10个对象,那么,存储的示意图如下:
                                                                        
    显然,因为函数的执行流程都是一致的。如果能够将函数单独分离出来,那么必然使得存储空间大大得到优化。也就是如下图所示。            
                                                                                                                      
                                                                                        
    显然,上述也正是编译器所设计的方案。
    所以在1中D的大小,正是说明了一个对象所占的空间大小只取决于该对象中的数据成员以及可能存在的vptr的大小。而函数是存储在对象空间之外的。

    问题是,既然调用的是同一段函数代码,那如何区分?
    C++使用this指针,来区分对象,类似于在每个函数的调用入口中,都加入了this指针的形式参数,以使得辨认出不同的对象。

    总结一下:
    • 函数的地址存在于代码区,不占用对象内存
    • 但是对于含有虚函数的类来说,实例化后的对象中必然存在一个虚拟指针vptr指向类的虚函数表,并占用一个指针的大小。

    待续


    参考文献:
    1. 侯捷  深度探索C++对象模型
    2. http://c.biancheng.net/cpp/biancheng/view/187.html

    展开全文
  • 毫克冰川 一个描述和实施针对冰川模拟问题的新型多网格技术的项目。... 这是我编写的一个纸和Python程序,目的是使我完全不清楚全近似存储(FAS)方案。 发表到 。 有关详细信息,请参见fas/README.md 。
  • 为解决火车站堆场模型及其数据结构问题,按有向图和无向图对常用堆场模型... 结果表明,相邻多重链表适用于功能顶点模型和承载顶点模型,正交链表适用于开关组顶点模型和轨迹顶点模型,邻接矩阵适用于路线冲突图模型
  • 云环境为利用数据存储、访问和处理等前沿技术实现目标主机的全球各地随意访问,并且云计算针对客户提供了部分常用的服务模型和部署模型。这些特性使得用户能够通过第三方服务商利用简单的操作就能提供数据存储功能,...
  • 研究光折变多重全息图分批热固定方法,依据热固定的基本理论模型研究离子补偿后的全息电子光栅在分批记录和定影过程中的光擦除特点。引入批间光擦除时间常数对多重全息图分批热固定的批间擦除特性进行定量描述,给出了...
  • C++对象模型

    2013-02-17 22:49:00
    单继承与多重继承的情况  <3>虚继承  观点:  <a>非静态数据成员在类实例内存中在内存中连续存储;  <b>静态数据成员不占类实例内存;  <c>一个子类的内存模型可以看成就是父类的...

    一、C++对象内存模型认知模式

      

    二、C++类数据成员内存模型

      <1>无继承情况

      <2>单继承与多重继承的情况

      <3>虚继承

      观点:

        <a>非静态数据成员在类实例内存中在内存中连续存储;

        <b>静态数据成员不占类实例内存;

        <c>一个子类的内存模型可以看成就是父类的各数据成员与自己新添加的数据成员的总和;

        <d>虚拟继承中,关于对象的数据成员内存布局问题有多种策略,自己注意测试;

    三、C++类函数成员的内存模型

      相关概念:C++的指针类型

      指针类型中包含了一个类似于 sizeof 的信息,或者其他的辅助信息,个sizeof的信息就告诉了系统你应该拿几个(连续)地址上的字节返回给我(猜想)

      <1>静态函数成员

        静态函数成员从实现的角度上讲,最大的特点就是编译器在处理静态函数成员的时候不会讲一个this指针压入其参数列表

        特点:

          <a>它不能直接读写class内的非静态成员,无论是数据成员还是函数成员;

          <b>它不能声明为const或是virtual;

          <c>它不是由类的实例来调用的,而是类作用域界定符;

      <2>非静态函数成员

        非静态函数的实现机制: 

        <a>改写非静态成员函数的函数原型,压入一个额外的this指针到成员函数的参数列表中,目的就是提供一个访问类的实例的非静态数据/函数成员的渠道;

        <b>将每一个对非静态数据/函数成员的读写操作改为经由this指针来读写;  

        <c>最惊讶的一步是,将成员函数改写为一个外部函数——Gotcha!这就是为什么sizeof(Class)的时候不会将非虚函数地址指针计算进去的原因,因为(非静态)成员函数都被搬到类的外面去了,并借助Name Mangling算法将函数名转化为一个全局唯一的名字。

      <3>虚拟成员函数

         <3.1>单继承下的虚拟成员函数    

    View Code
    class Parent {
    public:
        Parent():nParent(888) {}
        virtual void sayhello() { cout << "Perent()::sayhello()" << endl; }
        virtual void walk() { cout << "Parent::walk()" << endl; }
        virtual void sleep() { cout << "Parent::sleep()" << endl; }
    protected:
       int nParent;
    };
     
    class Child : public Parent {
    public:
        Child():nChild(88) {}
        virtual void sayhello() { cout << "Child::sayhello()" << endl; }
        virtual void  walk_child() { cout << "Child::walk_child()" << endl; }
        virtual void  sleep_child() { cout << "Child::sleep_child()" << endl; }
    protected:
       int nChild;
    };
     
    class GrandChild : public Child{
    public:
        GrandChild():nGrandchild(8) {}
        virtual void  sayhello() { cout << "GrandChild::sayhello()" << endl; }
        virtual void walk_child() { cout << "GrandChild::walk_child()" << endl; }
        virtual void sleep_grandchild() { cout << "GrandChild::sleep_grandchild()" << endl; }
    protected:
       int nGrandchild;
    };

        现在,我们使用一个int** pVtbl 来作为遍历对象内存布局的指针,这样可以方便地像使用数组一样来遍历所有的成员包括其虚函数表:

    View Code
    typedef void(*Fun)(void);
    
    GrandChild gc;
    
    int** pVtbl = (int**)&gc;
    
    cout << "[0] GrandChild::_vptr->" << endl;
    
    for(int i=0; (Fun) pVtbl[0][i]!=NULL; i++){
    
        pFun = (Fun) pVtbl[0][i];
    
        cout << "    ["<<i<<"] ";
    
        pFun();
    
    }
    
    cout << "[1] Parent.nParent = " << (int)pVtbl[1] << endl;
    
    cout << "[2] Child.nChild = " << (int) pVtbl[2] << endl;
    
    cout << "[3] GrandChild.nGrandchild = " << (int) pVtbl[3] << endl;

        运行结果如下:

        

        三个类的内存布局图

        

        <3.2>多重继承下的虚拟函数

            多重继承下的虚拟函数主要有一下几个麻烦:

            <a>几个父类都声明了相同原型的virtual函数;

            <b>有不止一个父类将其析构函数声明为虚拟;

            <c>一般的虚拟函数问题;

    View Code
    class Parent1{
    public:
       Parent1() : data_parent1(0.0){}
       virtual ~Parent1(){cout<<"Parent1::~Parent1()"<<endl;}
       virtual void speakClearly(){cout<<"Parent1::speakClearly()"<<endl;}
       virtual Parent1* clone() const{cout<<"Parent1::clone()"<<endl; return null;}
    protected:
       int data_parent1;
    };
     
    class Parent2{
    public:
       Parent2() : data_parent2(1.0){}
       virtual ~Parent2(){cout<<"Parent2::~Parent2()"<<endl;}
       virtual void mumble(){cout<<"Parent2::mumble()"<<endl;}
       virtual Parent2* clone() const{cout<<"Parent2::clone()"<<endl; return null;}
    protected:
       int data_parent2;
    };
     
    class Child : public Parent1, public Parent2
    {
    public:
       Child() : data_child(2.0){}
       virtual ~Child(){cout<<"Child::~Child()"<<endl;}
       virtual Child* clone() const{cout<<"Child::clone()"<<endl; return null;}
    protected:
       int data_child;
    };
    就内

            内存布局图:

            

          代码验证:

    View Code
    typedef void(*Fun)(void);
     
    int main()
    {
        Child c;
        Fun pFun;
     
        int** pVtbl = (int**)&c;
     
        cout << "[0] Parent1::_vptr->" << endl;
        pFun = (Fun)pVtbl[0][0];
        cout << "     [0] ";
        pFun();
     
        pFun = (Fun)pVtbl[0][1];
        cout << "     [1] ";
        pFun();
     
        cout << "    Parent1.data_parent1 = " << (int)pVtbl[1] << endl;
     
        int s = sizeof(Parent1)/4;
        cout << "[" << s << "] Parent2::_vptr->"<<endl;
        pFun = (Fun)pVtbl[s][0];
        cout << "     [0] "; pFun();
     
        pFun = (Fun)pVtbl[s][1];
        cout << "     [1] "; pFun();
     
        s++;
        cout << "    Parent2.data_parent2 = " << (int)pVtbl[s] << endl;
     
        s++;
        cout << "[3] Child.data_child = " << (int)pVtbl[s] << endl;
    }

          运行结果:

          

    备注:虚拟继承的出现就是为了解决重复继承中多个间接父类的问题的,

    四、C++对象模型总结

      <1>非静态数据成员都存放在对象所跨有的地址空间中,静态数据成员则存放于对象所跨有的地址空间之外;

      <2>非虚拟成员函数(静态和非静态)也存放于对象所跨有的地址空间之外,且编译器将其改写为普通的非成员函数的形式(以求降低调用开销);

      <3>对于虚拟成员函数,则借助vtbl和vptr支持。

      <4>对于继承关系,子类对象跨有的地址空间中包含了父类对象的实体,通过嵌入type-info信息进行识别和虚函数调用。

     

     

    内容参考:http://blog.csdn.net/outmanlee/article/details/6396621

    相关阅读:http://www.cnblogs.com/archy_yu/archive/2012/12/18/2822911.html

     

     

     

     

     

    转载于:https://www.cnblogs.com/BlueGeek/archive/2013/02/17/2915031.html

    展开全文
  • 2021年1月版的超越多重线性回归的仓库:在R中应用了广义线性模型和多层模型。可以在以下位置找到渲染的版本: : ,可以购买印刷版通过或在 版权 :copyright:2021,Taylor&Francis Group,LLC。 除非美国版权法许可...
  • 只针对存储的数据,而类图则在些基础上,增加了行为 建模的能力。在使用类图来表示E-R模型时,要注意遵 循以下策略 将表示E-R模型的类,用UML的标准构造型 “{persistent}"来表示; ● 展开类的结构性细节,并且加强...

    数据库逻辑模型的相关总结

    从某种意义.上说UML中的类图是E-R图的超集,E-R图
    只针对存储的数据,而类图则在些基础上,增加了行为
    建模的能力。在使用类图来表示E-R模型时,要注意遵
    循以下策略
    将表示E-R模型的类,用UML的标准构造型
    “{persistent}"来表示;

    展开类的结构性细节,并且加强关联和多重性分析;

    尽量消除循环关联、n-元关联

    展开全文
  • 模型对比与性能评估

    2021-04-25 18:57:49
    模型对比与性能评估 4.4.1 逻辑回归 优点 训练速度较快,分类的时候,计算量仅仅只和特征的数目相关; 简单易理解,模型的可解释性非常好,从特征的权重可以看到不同的特征对最后结果的影响;... 对多重
  • 4.多重继承 5.菱形继承 6.虚拟继承 1.对象模型是什么? 一般的,C++中类的对象模型是这样的: 非静态的成员变量被配置于对象中,排列顺序和声明顺序一致 静态的成员变量则被存储在对象之外;存储在全局的数据...
  • 对象关系映射(ORM)已经被使用了很长时间,以解决在编程过程中对象模型与数据模型在关系数据库中不匹配的问题。 Dapper是由Stack OverFlow团队开发的开源的,轻量级的ORM.相比于其他的ORM框架,Dapper速度非常快。 ...
  • 算法采用自助抽样技术对待分类数据中的属性进行裁剪和优化,解决了数据属性间的多重线性相关问题;算法结合贝叶斯算法的特点,采用动态增量存储树来解决动态样本数据流的存储问题,实现了无限动态数据流无信息失真的...
  • 图的存储表示有多种,在此我们只研究三种最为常用的存储表示方式:邻接矩阵(adjacency matrices),邻接表(adjacency lists),邻接多重表(adjacency multilists)。今天实现邻接矩阵的存储表示。 二.模型 三.邻接...
  • 举个例子,LVM和mdadm,这些时软件模型,主要功能是管理raw disks,合并他们到虚拟的连续的块地址空间,并且将其抽象话到更高级别的内核层。他们支持镜像,剥离和RAID5/6。无论如何,checksums是不支持的,...
  • 基于当前的实验条件, 在半导体量子点中考虑声子辅助跃迁效应去构建环形四能级半导体量子点电磁感应透明介质模型。利用多重尺度法解析地研究了其中的时间光孤子的动力学行为。结果发现, 可以通过调整声子辅助跃迁强度...
  • Task04 建模与调参 作者:Datawhale 小一 一、模型对比与性能评估 1. 逻辑回归 优点 训练速度较快,分类的时候,计算量仅仅只和特征的数目相关;...对多重共线性数据较为敏感,且很难处理数据不平
  • :针对统计假设检验的流和级联的多重检验校正 :在文本上学习图形模型的实验 使用此存储库时,请引用: @ARTICLE{Capdevila2018-Behaviormetrika, author = {Capdevila, Joan and Zhao, He and Petitjean, ...
  • 十字链表是邻接表和逆邻接表的组合,是对有向图的优化存储结构,容易求得顶点的出度和入度。除了结构复杂外,其实创建图算法的时间复杂度是和邻接表相同的,因此,在有向图的应用中,十字链表也是非常好的数据结构...
  • 一种用于存储和匹配个人身份信息(PII)记录的系统。 Piipan是计划完整性计划的参考模型,该计划旨在防止联邦政府资助但由州管理的福利计划多次注册。 在这种模式下,每个州定期向联邦政府运行的Piipan实例提交其...
  • 1.虚继承 虚继承是建立在多重继承之上的,当多重继承时,有可能存在重复继承的...虚继承类并不是存放在类对象空间中的,而是会在类对象空间中存放一个指针,来指向虚继承的存储空间。 用此例来探究数据成员的存...
  • 深度值存储在 depth Buff (z-Buffer) 之前结果中的z 是负值,进的大,越的小, 现在统一变成正值, 近处小, 远处大. z-Buffer 并不是一个排序算法, 只是找到了最小值, o(n)*三角形的个数. 考虑到抗锯齿, 多重...
  • 本章主要讨论类的成员变量(Data Member)的相关语义。...多重继承3.虚继承(virtual inheritance)4.多态下的成员操作有所区别的根本原因还是成员在对象中的存储结构。因此先理解这几种情况下对象的...
  • GitHub和邻近县中与科学和工程相关的存储库列表 内容 海洋 地球 空气 空间 技术 声学(水下) MatLab,Fortran ...-声学工具箱的GUI 不需要MatLab 海洋学(一般) -处理海洋数据集的有用命令的大杂烩 收音机 啪! .....
  • this指针调整的目的就是让对象指针正确的指向对象首地址,从而能正确的调用对象的成员函数或者说正确确定数据成员的存储位置。 多重继承下,有几种情况,第二个或者后续的基类会对虚函数的支持产生影响,即需要调整...
  • 化学结构信息与图论

    千次阅读 2019-09-29 15:46:05
    节点存储信息(标签),例如原子类型、电荷、多重性和质量,而边存储键合顺序。每个都可以具有关于芳族和立体异构的信息。至于键序,最好以π电子而不是边缘的形式给出节点,以反映实际的原子轨道和三维结构。 ...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 327
精华内容 130
关键字:

多重存储模型