0%

1. 内存管理函数的层次

从下图中可以看到,C++程序员处于的位置是最上层的Applications,用的最多的是newnew[],如果用容器,则内存基本不用管理。其次也可以调用malloc。至于最底层的操作系统级别的API,没有可移植性。它们之间的调用关系如上图的箭头所示。

阅读全文 »

5章:构造、析构、拷贝语意学

  • 可以定义和调用一个纯虚函数,不过只能被静态的调用(通过类作用域运算符),不能通过虚拟机制调用。

  • 你声明了一个纯虚析构函数,就必须定义它。因为在你提供了声明前提下,每一个derived class destructor会被编译器加以扩展,以静态调用的方式调用其“每一个virtual base class”以及“上一层base class”的destructor。因此,只要缺乏任何一个base class destructor的定义,就会导致链接失败

    读到这儿,你可能会有疑问,对于普通的类(没有虚机制参与进来,派生类的析构函数中也会逐一调用基类的析构函数)我们也没有提供它析构函数的,那为什么不会导致链接失败呢?这是因为你没有写析构函数,编译器会默默给你提供一个,以便于在后面的派生类的析构函数中调用它。这里的重点是你没有提供,也就是说你没有声明,如果你声明了,但没有提供定义,同样会导致链接失败。

  • 对于基类该不该将虚函数定义为const的,作者不建议。因为derived class中可能会修改自己的数据成员。

阅读全文 »

这里将要介绍的是一种在Linux平台实现的划词翻译工具,当然在考虑自己实现一个如此功能的工具前,我也是在网上搜索了一些在Linux平台实现的类似的开源工具,例如 pdfTranslatorpopup-dict,但它们的安装和配置都显得比较麻烦,而且使用起来也并不方便。

我实现这个工具的初衷本是方便自己看一些英文文献和书籍的,极为方便,考虑到分享出去可以让更多人受惠,因此这里详细介绍一下它的实现步骤。

阅读全文 »

4章:Function语意学

4.1 静态成员函数

function的调用方式

nonmember functionstatic member functionnonstatic member function的调用效率完全一样,因为,在内部都被编译器处理成相同的形式。而virtual member function的调用需要通过vptr所指向的virtual table,因此,效率有所降低。

static member function的主要特性就是它没有this指针。以下的次要特性统统根源于其主要特性:

阅读全文 »

3章:Data语意学

The size of class

1
2
3
4
5
6
7
8
class X
{
// char c; // 此时, sizeof(X) == 1, sizeof(Y) == 8, sizeof(Z) == 8, sizeof(A) == 16
char c; // 此时, sizeof(X) == 1, sizeof(Y) == 16, sizeof(Z) == 16, sizeof(A) == 24
};
class Y : public virtual X { };
class Z : public virtual X { };
class A : public Y, public Z { };

一个类的大小主要受三个因素的影响:

  1. 语言支持的特性所造成的负担

    比如,含虚函数的类会额外多一个vptr指针,含virtual base class会再多一个额外的指针(它或者指向virtual base class subobject,或者指向一个相关表格;表格中存放的若不是virtual base class subobject地址,就是其偏移量)。

  2. 编译器对于特殊情况所提供的优化处理

    现代编译器的对于空基类的优化处理:一个empty virtual base class被视为derived class object最开头的一部分,也就是说它并没有花费任何的额外空间。因为既然有了members,就不需要原本为了empty class而安插的一个char

  3. alignment(内存对齐)

    就是将数值调整到某数的整数倍。在64位计算机上,通常alignment8 bytes,以使bus的“运输量”达到最高效率。

阅读全文 »

2章:构造函数语意学

在这一章中,主要介绍编译器对于“对象构造过程”的干涉,以及对于“程序形式”和“程序效率”的冲击。

2.1 Default Constructor的构造操作

对于未声明构造函数的类,只有在以下四种情况下编译器才会为它们合成默认构造函数:

  • 类有一个类对象(Member Class Object)成员,且该成员含有默认构造函数(Default Constructor
  • 继承自带有默认构造函数(Default Constructor)的基类(Base class
  • 带有虚函数(Virtual function)的类
  • 继承自虚基类(Virtual base class)的类
阅读全文 »

前言

Simplifier是编译器的一部分,处于type checkingcode generation之间。它用来转换内部的程序表现。有3种转换是任何对象模型都需要的:

  1. 与编译器息息相关的转换(Implementation-dependent transformations

    例如,当parser看到这个表达式:

    1
    fct();

    它并不知道是否(a)这是一个函数调用操作,或者(b)这是overloaded calloperatorclass object fct上的一种应用。默认情况下,这个式子所代表的是一个函数调用,但是当(b)的情况出现,Simplifier就要重写并调换call subtree

  2. 语言语意转换(Language semantics transformations

    这包括constructor/destructor的合成和扩展、memberwise初始化、对于memberwise copy的支持、在程序代码中安插conversion operators、临时性对象,以及对constructor/destructor的调用。

  3. 程序代码和对象模型的转换(Code and object model transformations

    这包括对virtual functionsvirtual base classinheritance的一般支持、newdelete运算符、class objects所组成的数组、local static class instances、带有非常量表达式(nonconstant cxpression)之global object的静态初始化操作。

什么是C++对象模型?

  • 语言中直接支持面向对象程序设计的部分
  • 对于各种支持的底层实现机制
阅读全文 »

7章:模板与泛型编程

条款41:了解隐式接口和编译期多态
  • 哪一个重载函数被调用——发生在编译期

  • 哪一个virtual函数被绑定——发生在运行期

  • classtemplate都支持接口和多态

    class而言,接口是显式的,以成员函数的签名为中心,多态则通过virtual函数发生在运行期。对template而言,接口是隐式的,以有效表达式为中心,多态则通过template具现化和函数重载解析发生于编译期。

阅读全文 »

6章:继承与面向对象设计

条款32:确定你的public继承塑模出is-a关系
  • public继承”意味is-a。适用于base class身上的每一件事情一定也适用于derived class身上,因为每一个derived class对象也都是一个base class对象
阅读全文 »