0%

《深度探索C++对象模型》读书笔记

关于对象

对象实际需要的内存大小

  • nonstatic data members 总和大小
  • 由于alignment需求和填补(padding)上去的空间
  • 为了支持virtual而由内部产生的任何额外负担

指针类型

通过指针类型教导编译器如何解释某个地址中的内存内容及其大小。

  • 指向1000的int 类型的指针,在32位(int是4-bytes)的机器上,涵盖1000-1003的地址空间
  • 指向1000的string类型指针,是8-bytes,包括一个4-bytes的字符指针和一个用来表示字符串长度的整数

所以cast操作是一种编译器指令,它只影响被指出内存的大小和其内容。

C++程序设计模式

构造函数语义学

Constructor

对于一个class,若没有任何 user-declared constructor,那么会有一个default constructor被implicitly声明出来,这个声明通常是trivial(无能的,在STL中会采用直接内存操作的方式初始化)的,但在以下四种情况,是non-trivial的。

  • 带有Default Constructor的Member Class Object时,编译器声明的constructor会调用member class object的default constructor。这种情况下,即使有user-declared constructor,编译器也会按照Member Class Object定义的顺序补充调用他们的默认构造函数。
  • 带有Default Constructor的Base Class,derived class A需要合成一个constructor来调用父类的constructor,因此也是non-trival的,如此之后再继承该class A的子类,将把合成的A的constructor当作是显示声明的。
    • 此外即使A有user-declared的constructor,编译器也会扩充他们的每一个,按照顺序调用父类的default constructor。
    • 和第一种情况类似,Member Class Object的default constructor也会被扩充进来
  • 带有virtual function的class,
  • 带有一个virtual base class的class

Copy Constructor

  • 应用场景

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class X {...};
    // 第一种情况,等号赋值
    X x; // 由default constructor构造而来
    X xx=x; // 显式的以一个object的内容作为另一个class object的初值

    // 第二种情况,当作参数传入
    extern void foo(X x);
    void bar() {
    X xx;
    foo(xx); // 以xx作为foo()第一个参数的初值
    }

    // 第三种情况,当作返回值返回
    X foo_bar(){
    X *xx = new X();
    return *xx;
    }
  • 不遵照bitwise copy semiotics的情况

    • class中member objects中有声明copy constructor的情况(显式声明或者被编译器合成)

    • class继承自一个base class而后者存在一个copy constructor时

    • 当class 声明了一个或者多个virtual functions时

      • 例如

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        class ZooAnimal{
        public:
        ZooAnimal();
        virtual ~ZooAnimal();
        virtual void animate();
        virtual void draw();
        }
        class Bear : public ZooAnimal{
        public:
        Bear();
        void animate();
        void draw();
        virtual void dance();
        }
        Bear beer;
        ZooAnimal a = beer; // 会发生切割行为,逐位复制的方式将会造成vptr错误
    • 当class 派生自一个继承串链,其中有一个或多个virtual base classes时