设为首页 加入收藏

TOP

c++对象模型 构造函数、拷贝构造和拷贝复制(一)
2023-07-23 13:31:48 】 浏览:76
Tags:贝构造 贝复制

default constructor

  • default constructor只有在被编译器需要时,才会被合成出来,且合成出的constructor只执行编译器所需要的行动(并不对成员初始化)

含有default constructor的member class object

  • 在c++各个不同的编译模块(文件)中,编译器将合成的default constructor、copy constructor、destructor、assignment copy operator都用inline方式完成来避免合成多个default constructor
  • 若一个class没有任何constructor,而其内含的member object有default constructor,编译器则需要为此class合成default constructor
//B内含A
class A {
    public:
    	A();
    	A(int);
    ...
}

class B{
    public:
    B a;
    char* str;
}

//由于A有default constructor,而B内含A且B没有任何constructor,因此编译器需要为B合成一个default constructor,让其来调用A的default constructor处理B::a

//此处B中被合成的default constructor样子
inline
B::B()
{
    a.A::A();
}
  • 若class B中内含有一个及以上的member class objects,那么class B中的每一个constructor必须调用每一个member class的default constructor;如果是多个,编译器安插代码,会按照member objects在class中声明顺序来调用对应的constructor。因此,编译器会扩张已存在的constructor,在其中安插必要代码,使其先调用member class的default constructor

    //若我们为B写一个default constructor让其初始化str
    B::B() { str = 0; };
    
    //此时会出现一个问题,那就是B中已经存在一个我们写的default constructor,编译器不能为其再合成一个,那么我们便没法调用a的constructor。
    //此时,编译器会扩张已存在的constructor,在其中安插必要代码,使其先调用member class的default constructor
    
    //扩张后的B的default constructor内部结构
    B::B()
    {
        a.A::A();
        str = 0;
    }
    

含有default constructor 的 base class

  • 一个没有任何constructor的class派生自含有default constructor的base class,编译器会调用上层的default constructor,为derived class合成default constructor;若base class含有许多constructors,但没有default constructor,编译器会扩张每一个constructor,安插必要代码,以此调用必要的default constructor。因为存在其他constructors,并不会合成default constructor

含有virtual functions的 class

class A
{
    public:
    	virtual void do() = 0;
}

void do( const A& a ) { a.do(); };

void act()
{
    //B和C派生自A
    B b;
    C c;
    
    do( b );
    do( c );
}
  • 此时编译器会产生两个扩张行为:

    • virtual function table被编译器产出,其中存放virtual functions地址
    • 每一个class object中,vptr会被编译器合成,内含与之相关的vtbl地址
  • 并且,a.do()的virtual invocation会被改写

    //原本a.do()
    ( *a.vptr[1] )( &a )
    
    • 1表示do()在vtbl中的固定索引
    • &a表示交给被调用的do()实例的this指针
  • 为了让以上机制发挥效果,编译器必须为base和其derived class object的vpty设定初值,指向相关的virtual table地址。这样的任务会交给constructor做扩张

含有virtual base class的class

  • 由于在编译期时,virtual base class在每一个derived class object内存布局中位置不能够确定,因此编译器需要合成default constructor,在derived class object中的每一个virtual base classes中安插一个指针,以此确定其位置

copy constructor

default memberwise initialization

  • 以下三种情况会以一个object的内容作为另一个class object的初值:

    • 显示地以一个object内容作为另一个class object的初值

    • object被当做参数传给某函数

    • 函数传回class object

      //第一种
      class A {...};
      A a;
      
      A aa = a;
      
      //第二种
      void do1( A a );
      
      void do2()
      {
          A aa;
          
          foo(aa);
      }
      
      //第三种
      A do3()
      {
          A a;
          return a;
      }
      
  • 若一个class object没有explict copy constructor,而当class object以相同的class的另一个object作为初值时,此class object内部会把每一个内部或derived的data member的值,从另一个object拷贝一份到自己这,再以递归的方式进行memberwise initialization,但它并不拷贝member class object

  • memberwise initialization这一机制由bitwise copy semantics和default copy constructor实现,当class不展现bitwise copy semantics,编译器才会合成default copy constructor

  • 位拷贝(浅拷贝/bitwise copy semantics):编译器只是直接将data member的值或指针的值拷贝过来,并不拷贝member class object;也就是说这会导致多个指针指向同一对象

不展现bitwise copy semantics

  • 以下四种情况不会展现bitwise copy semantics:
    • class内含member object,而后者的class声明了copy constructor
    • class继承自base class,而base class声明了copy constructor
    • class声明一个及以上virtual functions
    • class派生自一个继承串链,其中含有一个及以上virtual base classes

对于第一、第二种情况

  • 若clas

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++ Null 指针的使用 下一篇fhq_treap 学习笔记

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目