内存模型和命名空间
单独编译
- c++程序分成三部分
- 第一部分:包含结构声明和使用这些结构的函数原型(头文件)
- 第二部分:包含与结构有关的函数代码(源代码文件)
- 第三部分:包含调用与结构相关的函数代码(源代码文件)
- 头文件包含了用户定义类型的定义;源代码文件包含操纵用户定义类型的函数代码
- 头文件中包含的内容:
- 函数原型
- #define 或 const 定义的符号常量
- 结构声明
- 类声明
- 模板声明
- 内联函数
-
将这些内容放在头文件中,并不会创建变量,而会在源代码声明的时候,告诉编译器如何创建该变量
头文件中,include使用""和<>的区别是:- 使用<>,c++编译器会在存储标准头文件的主机系统的文件系统中进行查找
- 使用"",c++编译器会首先查找当前工作目录和源代码目录的文件时
-
在调用头文件的时候,可能会出现头文件包含多次的情况,尤其是项目较为庞大的时候。可以通过使用#ifndef和#endif来避免该变量是否被定义。若COORDIN_H_被定义了,就会跳到endif后面
#ifndef COORDIN_H_
#define COORDIN_H_
struct polar
{
double distance;
double angle;
}
# endif
存储持续性、作用域和链接性
-
c++的4种存储方式:
- 自动存储持续性(局部变量)
- 静态存储持续性(static)
- 线程存储持续性(thread_local,生命周期和所属线程一样长)
- 动态存储持续性(new delete)
-
作用域和链接
- 作用域描述了名称在文件的多大范围可见
- 链接性描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性在内部的名称只能有一个文件中的函数共享
自动存储持续性
- 默认情况下,函数中声明的函数参数和变量的存储持续性为自动,作用域为局部,没有链接性
int i = 5;
cout << &i << endl;
{
cout << "测试" <<endl;
int i = 2;
cout << i << endl;
cout << &i << endl;
cout << "出来了" << endl;
}
cout << i <<endl;
cout << &i << endl;
cout << i <<endl;
静态持续变量
- 在c++中,为静态存储持续性变量提供了三种链接性 1. 外部链接性,可在其他文件中访问 2. 内部链接性,只能在当前文件中访问 3. 无连接性,只能在当前函数或代码块中访问
与自动变量相比,寿命更长
int global = 100; //第一种
static int test = 50; //第二种
int main()
{
...
retrn 0;
}
void func1(int n)
{
static int count = 0 ; //第三种
...
}
全局变量
- 链接性为外部的变量简称为外部变量(全局变量),存储持续性为静态,作用域为整个文件。外部变量在函数外部定义,可以在main()前面或头文件中定义它们。定义了之后可以在后面的任何函数当中去使用
- 每个使用外部变量的文件都必须声明它。服从"单定义规则"(变量只能有一次定义)
- 定义声明,给变量分配存储空间
- 引用声明,不分配存储空间,直接引用已有的变量(关键字extern)
- "单定义规则"指的是每个变量只能定义一次,而不是不能有同名变量。若局部变量中存在和全局变量同名的变量,全局变量会被隐藏掉
staic变量
- 将static限定符用于作用域为整个文件的变量时,该变量的链接性为内部。只能在所属文件中使用。使用static的静态变量,就不必担心其名称与其他文件中的全局变量发生冲突
静态存储性持续性、无链接性
将static限定符用于代码中定义的变量。在代码块中使用static,将导致局部变量的存储持续性为静态。意味着该变量只能在代码块中使用,但在代码块不处于活动状态是仍然存在
void test(int i);
int main()
{
test(6);
test(8);
}
void test(int i)
{
static int result = 0;
result = result + i;
cout << result << endl;
}
- 说明符和限定符
- c++关键字分为存储说明符和cv-限定符
- 存储说明符
- auto
- static
- register
- extern
- thread_local
- mutable
- cv-限定符
- const
- volatile
- 函数和链接性
- c++不允许在一个函数中定义另外一个函数,因此所有的函数的存储性都默认为静态。同样可以使用static将函数的链接性设置为内部。必须同时在原型和函数定义中都加上static
名称空间
传统的c++名称空间
- 声明区域是可以在其中进行声明的区域
- 潜在作用域。变量的潜在作用域从声明点开始到其声明区域的结尾
- c++对全部变量和局部变量的规则定义了一种名称空间层次,每个声明区域都可以声明名称,这些名称独立于其他声明区域中的声明名称。防止同名变量在不同函数中发生冲突的情况
新的名称空间特性
-
通过定义一种新的声明区域来创建命名的声明空间(namespace)
-
一个名称空间中的名称不会与另一个名称空降的同名变量发生冲突,同时允许程序的其他部分使用该名称空间中声明的东西
using声明和using编译指令。using声明使特定的标识符可用,using编译指令使整个名称空间可用-
using编译指令由名称空间名和它前面的关键字using namespace组成
using编译指令和using声明比较 -
using声明,像是声明了相应的名称。如果某个名称已经在函数中声明了,则不能用using声明导入相同的名称
-
using编译指令,将进行名称解析,像是包含了using声明和名称空间本身的最小声明区域中声明了名称一样
-
如果using编译指令导入一个已经在函数中声明的名称,则局部名称将隐藏名称空间名,就像隐藏同名全局变量一样
-
-
一般情况下,使用using声明比使用using编译指令更安全。因为using声明只导入指定名称,如果该名称与局部名称发生冲突,编译器会发出指示。using编译指令导入所有名称,包括并不需要的名称,如果和局部名称发生冲突,会被局部名称覆盖掉名称空间版本,但编译器并不会发出警告
可以将名称空间声明进行嵌套
namespace elements
{
namespace fire
{
int flame;
...
}
float water;
}
namespace myth
{
using Jill::fetch;
using namespace elements;
using std::cout;
using std::cin;
}
- 可以通过省略名称空间的名称来创建未命名的名称空间