C++ Primer读书笔记

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第六章抽象容器类型

1.我们能够定义的容器的类型有三个限制(实际上它们只适用于用户定义的类类型)

(1)元素类型必须支持等于操作符

(2)元素类型必须支持小于操作符前面讨论的所有关系操作符都用这两个操作符来实现

(3)元素类型必须支持一个缺省值对于类类型即指缺省构造函数。

所有预定义数据类型包括指针都满足这些限制C++标准库给出的所有类类型也一样。

第八章域和生命期

1.在全局域中定义的对象如果没有指定显式的初始值则该存储区被初始化为0因此

下面两个定义中var1 和var2 有相同的初始值0

int var1 = 0;

int var2;

2.既指定了关键字extern 又指定了一个显式初始值的全局对象声明将被视为该对象的定

义编译器将会为其分配存储区而且该对象后续的定义都被标记为错误例如extern const double pi = 3.1416; // 定义

const double pi; // 错误: 重复定义pi

关键字extern 也可以在函数声明中指定惟一的影响是将该声明的隐式属性在其他地

方定义变为显式的这样的声明有下列形式

extern void putValues( int*, int );

3.// ---- token.C 中----

int addToken( unsigned char tok ) { /* ... */ }

// ---- lex.C 中----

extern int addToken( char );

在C++中有一种机制通过它可以把函数参数的类型和数目编码在函数名中该机制

叫做类型安全链接type-safe-linkage 类型安全链接可用来帮助捕捉不同文件中函数声明不匹配的情况在前面的例子中unsigned char 型的参数和char 型参数的类型不同由于类型安全链接在lex.C 中声明的addToken()将会被标记为未定义的函数而token.C 中的定义则被视为定义了另外一个函数。

4.头文件为所向extern 对象声明函数声明以及inline 函数定义提供了一个集中的

位置这被称作声明的局部化localization 如果一个文件要使用或定义一个对象或函数时它必须包含include 相应的头文件。

5.符号常量和inline 函数可以被定义多次(在不同的程序文本文件中)。

在程序编译期间,在可能的情况下,符号常量(符号常量是任何const 型的对象)的值会代替该名字的出现。这个替代过程被称为常量折叠constant folding。

但是,在某些情况下不可能做到符号常量的常量折叠过程。在这样的情况下最好把常量的初始化移到某一个程序文本文件中,这可以由显式地声明常量为ex tern 来实现。例如

// ----- 头文件-----

const int buf_chunk = 1024;

extern char *const bufp;

// ----- 程序文本文件-----

char *const bufp = new char[buf_chunk];

虽然bufp 被声明为const,但是它的值却无法在编译时刻被计算出来,它的初始化值是一个要求调用库函数的new 表达式,如果bufp 在头文件中被初始化那么它将在每个包含它的文件中被定义这不但浪费了空间,而且可能与程序员的意图不符。

6.如果编译器在调用点上没有内联该函数

则编译器会为该函数生成一个定义放到可执行文件中如果在多个文件中生成同一函数的定义则会产生一个不必要的过大的可执行文件。

如果出现下列情况多数编译器都会产生警告一般情况下这要求打开编译器的警告模式

(1)函数的定义使其根本不可能做成inline 函数例如编译器可能抱怨函数过于复杂而无法内联在这种情况下如果可能就应重写该函数否则去掉inline 指示符把函数定义放到程序文本文件中。

(2)函数的特殊调用不能被内联例如在C++的最初实现AT&T(cfront) 中同—表

达式中的一个inline 函数的第二次调用就无法被内联在这种情况下我们可

以把表达式重新改写成两个独立的inline 函数调用。

在把一个函数声明为inline 乊前我们必须分析它的运行时刻行为以确信该函数被内联对于这部分代码来说确实是必要的建议把那些天生无法内联的函数不声明为inline 并且不放在头文件中。

7.未初始化的自动对象包含一个随机的位模式是该存储区上次被使用的结果它

的值被称为未指定的(unspecified)。因为与自动对象相关联的存储区在函数结束时被释放所以应该小心使用自动对象的地址。当一个自动变量的地址被存储在一个生命期长于它的指针时该指针被称为空悬指针(dangling pointer)这是一个严重的程序员错误因为它所指的内容是不可预测的如果该地址的值正好合适因此程序就不会产生段错误该程序可能一直执行到完成但是给出的是一个无效的结果。

8.未经初始化的静态局部对象会被程序自动初始化为0。

9.动态分配的对象被分配在程序的空闲存储区free store 的可用内存池中。

程序员用new 表达式创建动态分配的对象用delete 表达式结束此类对象的生命期动态分配的对象可以是单个对象也可以是对象的数组在空闲存储区中分配的数组的长度可以在运行时刻计算。在本节中关于动态分配的对象我们将会了解到三种形式的new 表达式一种支持单个对象的动态分配另一种支持数组的动态分配第三种形式被称为定位new 表达式。

单个对象的动态分配与释放

例如

new int;

从空闲存储区分配了一个int 型的对象类似地

new iStack;

分配了一个iStack 类对象

new 表达式本身并不是十分有用我们如何使用被分配的对象呢?空闲存

储区的一个特点是其中分配的对象没有名字。new 表达式没有返回实际分配的对象而是返回指向该对象的指针对该对象的全部操作都要通过这个

指针间接完成例如

int *pi = new int; 该new 表达式创建了一个int 型的对象由pi 指向它。

空闲存储区的第二个特点是分配的内存是未初始化的。空闲存储区的内存包含随机的位模式它是程序运行前该内存上次被使用留下的结果测试

it ( *pi == 0 )

总是会失败因为由pi 指向的对象含有随机的位因此我们建议对用new 表

达式创建的对象进行初始化程序员可以按如下方式初始化上个例子中的

相关文档
最新文档