Chapter 13 Unusual Data Types
不常见的数据类型
13.1 Structure 结构体
“结构体”这一术语指的是使用其他类型组建的数据。
通常情况下,你会希望创建类而非结构体,这样除了能使用结构体可以提供的公用数据成员外,还能利用所提供的私密性和功能性。但是有时直接操纵成块的数据会十分方便,下面就列出一些使用结构体的理由:
1. 用结构体来明确数据关系。结构体把相关联的一组数据聚集在一起。
2. 用结构体简化对数据块的操作。
3. 用结构体简化参数列表。
你可以利用结构体变量简化子程序的参数列表。例如:
HardWayRoutine(name, address, phone, ssn, gender, salary)
下面的方法则要简单的多。
EasyWayRoutine(employee)
但是要注意,信息应该按照有必要了解(need-to-know)的原则进行传递。
4. 用结构体来减少维护。
13.2 Pointers 指针
·Paradigm For Understanding Pointers 用来理解指针的范例
1. Location in Memory 内存中的位置
内存中的一个位置就是一个地址,常用16进制表示。32位处理器中的一个地址用32位的值来表示。指针本身包含这个地址。为了使用该指针所指向的数据,就必须访问该地址,解释该地址的内存内容。
2. Knowledge of how to interpret the Contents 如何解释指针所指的内容
如何解释内存中某个位置的内容,是由指针的基类型(base type)决定的。如果某指针指向整数,这就意味着编译器会把该指针指向内存位置的数据解释为一个整数。
·General Tips on Pointers 使用指针的一般技巧
对解决很多类型的程序错误来说,最容易的一部分是定位错误,而最难的一部分是更正错误。然而指针错误的情况有所不同。通常,指针错误都产生于指针指向了它不应该指向的位置。当你通过一个怀了的指针变量赋值时,会把数据写入本不该写值的内存区域。这称为“内存破坏(memory corruption)”。
因此,指针错误的大部分工作量便是找出它的位置。
1. 把指针操作限制在子程序或者类里面
2. 同时声明两个指针
在靠近变量声明的位置为改变量赋初始值通常是一项好的编程实践,在使用指针时,应用这条原则会更有价值。
3. 在与指针分配相同的作用域中删除指针。
要保持指针分配和释放操作的对称性。如果你需要在一个单一作用域内使用指针,那么就应该在次作用域范围内用New分配指针,用Delete释放指针。如果一个子程序分配了内存,却指望调用它的代码来释放该内存,这样造成的不一致的处理方式很容易出错。
4. 在使用指针之前检查指针
5. 先检查指针所引用的变量在使用它
6. 用狗牌字段来检测损毁的内存
“标记字段”(tag field)或者“狗牌(dog tag)”是指你加入结构体的一个仅仅用于检测错误的字段。
7. 增加明显的冗余
8. 用额外的指针变量来提高代码清晰度
9. 简化复杂的指针表达式
10. 画一个图
11. 按照正确的顺序删除链表中的指针
12. 分配一片保留的内存后备区域
13. 粉碎垃圾数据
14. 在删除或者释放指针之后把它们设为空值。
15. 在删除之前检查非法指针
16. 跟踪指针分配情况
17. 编写覆盖子程序,集中实现避免指针问题的策略
C++-Pointer
C-Pointer
13.3 Global Data 全局数据
全局数据可以在程序中任意一个位置访问。这个概念有时被延伸到作用域比局部变量更广的变量——例如可以在一个类内部的任意位置进行访问的类变量。但是,在一个类的内部任意位置访问,并不意味该变量是全局的。
·Common Problems with Global Data 与全局数据有关的常见问题
人们指出了使用全局数据的许多问题,实际上这些问题都可以归结到下面集中情况。
1. 无意间修改了全局数据
2. 与全局数据有关的奇异的和令人激动地别名问题
3. 与全局数据有关的代码重入(re-entrant)问题
4. 全局数据阻碍代码重用
5. 与全局数据有关的非确定的初始化顺序事宜。
6. 全局数据破坏了模块化和智力上的可管理性。
·Reasons to Use Global Data 使用全局数据的理由
1. 保存全局数据
2. 模拟具名变量
3. 模拟枚举类型
4. 简化对极其常用的数据的使用
5. 消除流浪数据
· Use Global Data Only as a Last Resort 只有万不得已时才使用全局数据
1. 首先把每一个变量设置为局部,仅当需要时才把变量设置为全局。
2. 区分全局变量和类变量
3. 使用访问器子程序
· Using Access Routines Instead of Global Data 用访问器子程序取代全局数据
你用全局数据能做的任何事情,都可以用访问器子程序做得更好。
1. Advantage of Access Routines 访问器子程序的优势
2. How to use Access Routines 如何使用访问器子程序
下面是在你的语言中没有内置对类的支持的情况下,使用访问器子程序来隐藏全局变量的一些详细指导原则。
A. 要求所有的代码通过访问器子程序来存取数据
B. 不要把你所有的全局数据都扔在一处
C. 用锁定来控制对全局变量的访问
D. 在你的访问器子程序里构建一个抽象层。
E. 使得对一项数据的所有访问都发生在同一个抽象层上。
·How to Reduce the Risks of Using Global Data 如何降低使用全局数据的风险
1. 创建一种命名规则来突出全局变量
2. 为全局的全局变量创建一份注释良好的清单
3. 不要用全局变量来存放中间结果
4. 不要把所有的数据都放在一个大对象中并到处传递,以说明你没有使用全局变量。
Key Points 要点
1. 结构体可以使得程序更简单,更容易理解,以及更容易维护。
2. 每当你打算使用结构体的时候,考虑使用类是不是会工作的更好?
3. 指针很容易出错。用访问器子程序或类以及防御式编程实践来保护自己的代码。
4. 避免用全局变量,不只是因为他们很危险,还是因为你可以用其他更好的方法取代它们。
5. 如果你不得不使用全局变量,那么就通过访问器子程序来使用它。访问器子程序能够为你带来全局变量所能带来的一切优点,还有一些额外好处。