《第9章 内存模块和名称空间》

9.1 单独编译(单独编译+链接)

  1. 组织程序的策略:头文件(包含结构声明和使用这些结构的函数的原型);源代码文件(包含于结构相关的函数的代码);源代码文件(包含调用与结构相关的函数的代码)。
  2. 请不要将函数定义或变量声明放到头文件中。
  3. 头文件中常包含的内容:函数原型;使用#define或const定义的符号常量;结构声明;类声明;模板声明;内联函数。
  4. 关于使用引号和尖括号的区别:如果文件名包含在尖括号中,则C++编译器将在存储标准头文件的主机系统的文件系统中进行查找;但如果文件名包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录。
  5. 仅当以前没有使用预处理器编译指令#define定义名称COORDIN_H_时,才处理#ifndef和#endif之间的语句。
  6. #ifndef COORDIN_H_
    #define COORDIN_H_
    //place include file contents here
    #endif

    在UNIX系统中编译由多个文件组成的C++程序:给出两个源文件的UNIX编译命令;预处理器将包含的文件与源代码结合起来;(临时文件);编译器创建每个源代码文件的对象代码文件;链接程序将对象代码文件与库代码和启动代码结合在一起,生成可执行文件。

9.2 存储持续性、作用域和链接性

9.2.1 作用域和链接

  1. 作用域(scope)描述了名称在文件(翻译单元)的多大范围内可见。链接性(linkage)描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件中的函数共享。
  2. 静态变量的作用域是全局还是局部取决于它是如何被定义的。

9.2.2 自动存储持续性

  1. 在默认情况下,在函数中声明的函数参数和变量的存储持续性为自动,作用域为局部,没有链接性。
  2. 自动变量只在包含它们的函数或代码块中可见。
  3. 使用关键字auto来显式地指出存储类型,但此关键词只能用于默认状态下为自动的变量。
  4. 自动变量和堆栈:在相邻的内存单元中;程序使用两个指针来跟踪堆栈;堆栈是先进后出的;新值没有被删除,但不再被标记,它们所占据的空间将被下一个将值加入到堆栈中的函数调用所使用。
  5. 关键词register提醒编译器,用户希望它通过使用CPU寄存器,而不是堆栈来处理特定的变量,从而提供对变量的快速访问,但是编译器并不一定会满足上述请求。
  6. 如果变量被存储在寄存器中,则没有内存地址,因此不能将地址操作符用于寄存器变量。
  7. 常规局部变量、使用auto声明的局部变量以及使用register声明的局部变量的存储周期性都是自动的,作用域都是局部的,也都没有链接性。

9.2.3 静态持续变量

  1. 编译器将分配固定的内存块来存储所有的静态变量,这些变量在整个程序执行期间一直存在。
  2. 如果没有显式地初始化静态变量,编译器就将把它设置为0。
  3. 要想创建链接性为外部的静态持续变量,必须在代码块的外面声明它,在程序的其它文件中也可以使用该变量。
  4. 要想创建链接性为内部的静态持续变量,必须在代码块的外面声明它,并使用static限定符,只能在包含上述代码的文件中使用该变量。
  5. 要创建没有链接性的静态持续变量,必须在代码块内声明它,并使用static限定符,即使函数没有执行,变量也会存在内存中。
  6.  
    5种变量存储方式
    存储描述持续性作用域链接性如何声明 
    自动自动代码块在代码块中(可使用关键字auto) 
    寄存器自动代码块在代码块中,使用关键字register 
    静态,无链接性静态代码块在代码块中,使用关键字static 
    静态,外部链接性静态文件外部在函数外面 
    静态,内部链接性静态文件内部在函数外面,使用关键字static 
  7. 使用关键字extern来重新声明之前定义过的外部变量。

  8. 使用extern对变量进行重新声明,意思是通过以前被外部定义的名称使用该变量。

  9. 定义声明(defining declaration)或简称为定义(declaration),给该变量分配存储空间;引用声明(referencing declaration)或简称为声明(declaration),不给变量分配存储空间;不能在引用声明中初始化变量。

  10. 作用域解析操作符(::),当放在变量名称前面时,该操作表示使用变量的全局版本。

  11. const char * const months[12]第一个const防止字符串被修改,第二个const确保数组中每个指针始终指向它最初指向的字符串。

  12. 在多文件程序中,可以在一个文件(且只能在一个文件)中定义一个外部变量,使用该变量的其它文件必须使用关键字extern声明它。

  13. 如果文件中定义了一个静态局部变量,其名称与另一个文件中声明的常规外部变量相同,则在该文件中,静态变量将隐藏常规外部变量。

  14. 应使用外部变量在多文件程序的不同部分之间共享数据;应使用链接性为内部的静态变量在同一个文件中的多个函数之间共享数据。

  15. 在代码块中使用static时了,将导致局部变量的存储持续性为静态的。这意外着虽然该变量只在该代码块中可用,但它在该代码块不处于活动状态时仍然存在。

  16. 如果初始化了静态局部变量,则程序只在启动时进行一次初始化,以后再调用函数时,将不会像自动变量那样再次被初始化。

9.2.4 说明符和限定符

  1. 存储说明符:auto;register;static;extern;mutable。
  2. cv-限定符:const;volatile。const表明内存被初始化后,程序将不能再对它进行修改;volatile关键字表明即使程序代码没有对内存单元进行修改,其值也可能发生变化。
  3. mutable表示即使结构(或类)变量为const,其某个成员也可以被修改。
  4. 在默认情况下全局变量的链接性为外部的,但const全局变量的链接性为内部的。也就是说,在C++看来,全局const定义就像使用了static说明符一样。
  5. 不能在多个文件中定义同一个全局变量。
  6. 出于某种原因,程序员希望某个常量的链接性为外部的,则可以使用extern关键字来覆盖默认的内部链接性,在这种情况下,必须在所有使用该常量的文件中使用extern关键字来声明它。

9.2.5 函数和链接性

  1. C++不允许在一个函数中定义另外一个函数,因此所有函数的存储持续性都自动为静态的,即在整个程序执行期间都一直存在。
  2. 可以在函数原型中使用关键字extern来指出函数是在另一个文件中定义的。
  3. 使用关键字static将函数的链接性设置为内部的,使之只能在一个文件中使用,必须同时在原型和函数定义中使用该关键字。
  4. 单定义规则:在多文件程序中,只能有一个文件包含该函数的定义,但使用该函数的每个文件都应该包含其函数原型。

9.2.6 语言链接性

  1. C++语言链接(C++ language linkage)
  2. 用函数原型来指出要使用的约定
  3. 名称矫正或名称修饰

9.2.7 存储方案和动态分配

  1. 可以在一个函数中分配动态内存,而在另一个函数中将其释放。
  2. 通常编译器使用3块独立的内存,一块用于静态变量(可能再细分),一块用于自动变量,另外一块用于动态存储。
  3. 使用new来设置指针的语句必须位于函数中,因为只能使用常量表达式来初始化静态存储变量。

9.3 布局new操作符

  1. 通常new负责在堆(heap)中找到一个足以能够满足要求的内存块,而布局new操作符让您能够指定要使用的位置。
  2. #include<new>,它提供了这种版本的new操作符的原型;然后将new操作符用于提供了所需地址的参数。
#include<new>
struct chaff
{
    char dross[20];
    int slag;
}
char buffer1[50];
char buffer2[500];

int main()
{
    chaff *p2;
    int *p4;
    p2 = new (buffer1) chaff;//place structure in buffer1
    p4 = new (buffer2) int[20];//place int array in buffer2
    ...
}

     3.布局new操作符使用传递给它的地址,它不跟踪哪些内存单元已被使用,也不查找未使用的内存块,这将一些内存管理的负担交给了程序员。

9.4 名称空间

9.4.1 传统的C++名称空间

  1. 声明区域(declaration region),是可以在其中进行声明的区域。
  2. 潜在作用域(potential scope)与作用域不同。变量并非在其潜在作用域内的任何位置都是可见的,它可能被另一个在嵌套声明区中声明的同名函数隐藏,变量对程序而言可见的范围被称为作用域(scope)。

9.4.2 新的名称空间特性

  1. 关键字namespace
  2. 名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。在默认情况下在名称空间中声明的名称的链接性为外部的。
  3. 全局名称空间(global namespace),对应于文件级声明区域。
  4. 名称空间是开放的,即可以吧名称加入到已有的名称空间中。
  5. 未被修饰的名称被称为未限定的名称;包含名称空间的名称被称为限定的名称。
  6. using声明使特定的标识符可用,using 编译指令使整个名称空间可用。
  7. 如果使用using编译指令导入一个已经在函数中声明的名称,则局部名称将隐藏名称空间名,就像隐藏同名的全局变量一样。
  8. 可以用嵌套式名称空间来创建一个包含常用using声明的名称空间。
  9. 可以在名称空间中使用using编译指令和using声明。
  10. using编译指令是可传递的。
  11. 可以给名称空间创建别名,可以使用这种技术来简化对嵌套名称空间的使用。
  12. 可以通过省略名称空间的名称来创建未命名的名称空间,在该名称空间中声明的名称的潜在作用域为:从声明点到该声明区域末尾。从这方面看,它们与全局变量相似。
  13. C++标准不赞成在名称空间和全局作用域中使用关键字static。

9.4.3 名称空间范例

9.4.4 名称空间及其前途

  1. 不要在头文件中使用using编译指令。
  2. 导入名称时,首选使用作用域解析操作符或using声明的方法。
  3. 对于using声明,首选将其作用域设置为局部而不是全局。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值