《C++ Primer Plus》读书笔记之七—内存模型和名称空间

第九章 内存模型和名称空间

  1、不要将函数定义或者变量声明放到头文件中。

  2、头文件常包含的内容:函数原型、使用#define或者const定义的常量、结构声明、类声明、模板声明、内联函数。

  3、避免多次包含同一个头文件的技术:#ifndef/#endif。仅当以前没有使用预处理器编译指令#define定义一个头文件名称时,才处理#ifndef和#endif之间的语句。

  4、链接性描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件中的函数共享。自动变量(函数定义中声明的变量(包括函数参数))的名称没有链接性,因为它们不能共享,作用域为局部。

  5、常用的管理自动变量的方法是留出一段内存,并将其视为栈,以管理变量的增减。栈的默认长度取决于实现,但编译器通常提供改变栈长度的选项。程序使用两个指针来跟踪栈,一个指向栈底,另一个指向栈顶,即下一个可用的内存单元。函数结束时,栈顶指针被重置为函数被调用前的值,从而释放新变量使用的内存。新变量没有被删除,但不再被标记,它们所占用的空间被下一个将值加入到栈中的函数所使用。

  6、C++支持使用register关键字来声明局部变量,说明该变量将被频繁使用。寄存器变量是另一种形式的自动变量。CPU访问寄存器中的值的速度比访问栈中的内存快。但编译器不一定会满足此声明。注:在寄存器中的变量没有内存地址,因此不能将地址操作符用于寄存器变量。

  7、C++为静态存储持续性变量提供三种链接性:外部、内部和无链接性。这三种链接性都在整个程序执行期间存在,与自动变量相比,它们的寿命更长。编译器将分配固定的内存块来存储所有的静态变量,这些变量在整个程序执行期间一直存在。

  8、链接性为外部的静态持续变量:必须在代码块的外面声明它,可以在程序的其他文件中使用它,即在其他文件中用extern对该变量进行引用声明,而且只有一个文件包含了该变量的外部定义;链接性为内部的静态持续变量:必须在代码块的外面声明它,并使用static限定符,表明该变量只能在其所属的文件中使用;无链接性静态持续变量:必须在代码块内声明它,并使用static限定符,这意味着虽然该变量只在该代码块中可用,但它在该代码块不处于活动时仍然存在。例子如下:

  ...

  int global=1000;   // 链接性为外部的静态变量

  static int one_file=50;   // 链接性为内部的静态变量

  int main()

  {

    ...

  }

  void fun1(int n)

  {

    static int count=0;  // 无链接性静态持续变量

  }

  9、定义与全局变量同名的局部变量后,局部变量将隐藏全局变量。当将(::)放在变量名称前面时,该操作符表示使用变量的全局版本。

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

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

  12、volatile关键字表明,即使程序代码没有对内存单元进行修改,其值也可能发生变化。它的作用时为了改善编译器的优化能力。如果不将变量声明为volatile,则编译器将进行这种优化;将变量声明为volatile,相当于告诉编译器,不要进行这种优化。

  13、mutable用来指出,即使结构(或类)变量为const,其某个成员也可以被修改。

  14、默认情况下全局变量的链接性为外部的,但const全局变量的链接性为内部的(就像使用了static说明符一样)。如果希望某个常量的链接性为外部的,则可以使用extern来覆盖默认的内部链接性。如:extern const int a=1;

  15、C++不允许在一个函数中定义另外一个函数,因此所有函数的存储持续性都自动是静态的,即整个程序执行期间都一直存在。在默认情况下,函数的链接性为外部的,即可以在文件间共享。也可以用static将函数的链接性设置为内部的,使之只能在一个文件中使用,必须同时在原型和函数定义中使用该关键字。

  16、对于非内联函数,程序中只能包含一个定义。

  17、C语言链接性:在C语言中,一个名称只对应一个函数。C语言编译器可能将fun这样的函数名翻译为_fun。C++语言链接性:C++中,同一个名称可能对应多个函数,必须将这些函数翻译为不同的符号名称。

  18、如果在C++程序中使用C库中预编译的函数,为了解决名字的匹配问题,可以用函数原型来指出要使用的命名约定:

  extern “C” void fun();  // 使用C语言链接性

  extern void fun();  // 使用C++语言链接性

  extern “C++” void fun();  // 使用C++语言链接性

  19、使用new来设置指针的语句必须位于函数中,这是因为只能使用常量表达式来初始化静态存储变量。

  20、布局new操作符:指定要使用的位置。例子:

  char buffer[500];

  int *p;

  p=new (buffer) int[20];  //  从buffer中分配空间给一个包含20个元素的int数组。

  注:buffer指定的是静态内存,而delete只能用于这样的指针:指向常规new操作符分配的堆内存。也就是说,数组buffer位于delete的管辖区之外。所以不用delete来释放使用new操作符分配的内存。

  21、声明区域:可以在其中进行声明的区域。潜在作用域:从声明点开始,到其声明区域的结尾。因此潜在作用域比声明区域小,这是由于变量必须定义后才能使用。

  22、名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。在默认情况下,在名称空间中声明的名称的链接性是外部的(除非它引用了常量)。

  23、任何名称空间中的名称都不会与其他名称空间中的名称发生冲突。

  24、通过作用域解析操作符(::)来访问名称空间的名称。

  25、using声明使特定的标识符可用,using编译指令使整个名称空间可用。  

  26、注:假设名称空间和声明区域定义了相同的名称。如果试图使用using声明将名称空间的名称导入该声明区域,则这两个名称会发生冲突,从而出错。如果使用using编译指令将名称空间的名称导入该声明区域,则局部版本将隐藏名称空间不版本。

  27、一般来说,使用using声明比使用using编译指令更安全,这是由于它只导入指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译指令导入所有名称,包括可能不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间的版本,而编译器并不会发出警告。

  28、名称空间的其他特性:

  ①namespace A

  {

    namespace B

     {

      int a;

      ...

     }  

  }

  访问a的话:A::B::a。也可以使用using编译指令使内部的名称可用:using namespace A::B;②另外,也可以在名称空间中使用using编译指令和using声明:

  namespace myth

  {

    using Jill::fetch;

    using namespace element;

    using std::cout;

    using std::cin;

  }

  访问Jill::fetch,可以这样:std::cin>>myth::fetch;也可以这样:std::cout<<Jill::fetch;

  using namespace myth;(添加了element名称空间)和using namespace myth;using namespace element;等价。

  ③可以给名称空间创建别名。namespace my_love{...};  namespace ml=my_love;

  29、不能在未命名名称空间所属文件之外的其他文件中,使用该名称空间中的名称,因此这种方法可以替代链接性为内部的静态变量。例如:

   static int one_file;   // 链接性为内部的静态变量

  int main()

  {

    ...

  }

  可以这样:

  namespace

  {

    int one_file;  // 链接性为内部的静态变量

  }

  int main()

  {

   ...

  }

  30、在名称空间中声明的函数名的作用域为整个名称空间,因此定义和声明必须位于同一个名称空间中。

原文地址:https://www.cnblogs.com/smile233/p/8796511.html

时间: 2024-10-24 01:54:54

《C++ Primer Plus》读书笔记之七—内存模型和名称空间的相关文章

C++ primer plus读书笔记——第9章 内存模型和名称空间

第9章 内存模型和名称空间 1. 头文件常包含的内容: 函数原型. 使用#define或const定义的符号常量. 结构声明. 类声明. 模板声明. 内联函数. 2. 如果文件名被包含在尖括号中,则C++编译器将在存储标准头文件的主机系统的文件系统中查找.但如果头文件名包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录(或其他目录,这取决于编译器).如果没有在那里找到头文件,则将在标准位置中查找.因此在包含自己的头文件时,应使用引号而不是尖括号. 3. 链接程序将目标文件代码.库代码和

《C++ Primer Plus》第9章 内存模型和名称空间 学习笔记

C++鼓励程序员在开发程序时使用多个文件.一种有效的组织策略是,使用头文件来定义用户类型,为操纵用户类型的函数提供函数原型,并将函数定义放在一个独立的源代码文件中.头文件和源代码文件一起定义和实现了用户定义的类型及其使用方式.最后,将main()和其他使用这些函数的函数放在第三个文件中.C++的存储方案决定了变量保留在内存中的事件(存储持续性)以及程序的哪一部分可以访问它(作用域和链接性).自动变量在代码块(如函数体或函数体中的代码块)中定义的变量,仅当程序执行到包含定义的代码块时,它们才存在,

《java并发编程实战》读书笔记13--Java内存模型,重排序,Happens-Before,

第16章 Java内存模型 终于看到这本书的最后一章了,嘿嘿,以后把这本书的英文版再翻翻.这本书中尽可能回避了java内存模型(JMM)的底层细节,而将重点放在一些高层设计问题,例如安全发布,同步策略等.它们的安全性都来自于JMM.本章将介绍Java内存模型的底层需求以及所提供的保证. 16.1 什么是内存模型,为什么需要它 16.1.1 平台的内存模型 在共享内存的多处理体系架构中,每个处理器都拥有自己的缓存,并且定期地与住内存进行协调.在不同的处理器架构中提供了不同级别的缓存一致性.要想确保

《C++ Primer Plus 6th》读书笔记 - 第九章 内存模型和名称空间

1. 单独编译 1.1 头文件中常包含的内容: 函数原型 使用#define或const定义的符号常量 结构声明 类声明 模板声明 内联声明 1.2 只需将源代码文件加入到项目中,而不用加入头文件.这是因为用#include管理头文件. 1.3 避免多次包含同一个头文件 1 #ifndef COORDIN_H_ 2 #define COORDIN_H_ 3 // place include file contents here 4 #endif 2. 存储持续性.作用域和链接性 1. 存储方案:

[C++ Primer Plus] 第9章、内存模型和名称空间——(一)程序清单

程序清单9.11-13(名称空间示例) namesp.h 头文件:常量.结构定义.函数原型 1 //namesp.h 2 #include<string> 3 //creat the pers and debts namespace 4 namespace pers //包含Person结构的定义和两个函数原型 5 { 6 struct Person 7 { 8 std::string fname; 9 std::string lname; 10 }; 11 void getPerson(Pe

[C++ Primer Plus] 第9章、内存模型和名称空间——(二)课后习题

头文件 golf.h 1 //golf.h --for pe9-1.cpp 2 3 const int Len = 40; 4 struct golf 5 { 6 char fullname[Len]; 7 int handicap; 8 }; 9 10 void setgolf(golf &g, const char *name, int hc); 11 12 int setgolf(golf &g); 13 14 void handicap(golf &g, int hc);

第九章:内存模型与名称空间

9.1题:构造函数的调用 #include<iostream> #include<cstring> using namespace std; class Golf { string m_name; int m_handicap; public: Golf():m_name("Sam"),m_handicap(24){};//析构函数的赋值,m_name和m_handicap在进入大括号之前就已经初始化 void show() { cout << m_

C++ Primer 3rd 读书笔记

C++ Primer 3rd 读书笔记1/2 分类: C/C++/VC2014-04-08 20:43 318人阅读 评论(0) 收藏 举报 第一章    开始 1.       C++中标准的头文件是不带.h后缀的.如下代码值得注意: #include <iostream.h> void sayHello() { cout<<"Hello World!"; } void main() { sayHello(); } #include <iostream&

[笔记]JAVA内存模型与线程

JAVA线程  工作内存  主内存 java内存模型中的八种操作: lock    unlock    read     load     use      assign      store     write 八种基本操作必须满足的规则 volatile 当一个变量被定义成volatile之后,它将具备两种特性 一是保证此变量对所有线程的可见性("可见性"是指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的.) 二是禁止指令重排序优化(普通的变量仅仅会保证在该方法