C++ Primer第9章相关问题及总结

1.头文件命名问题

如果文件名包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录(或其他目录,这取决于编译器),如果没有在那里找到头文件,则将会在标准位置查找,因此在包含自己的头文件时,应使用引号而不是尖括号。

2.自动存储持续性

在代码块定义的变量,它的生命即该变量的存在时间和作用域将被限制在该代码块中,这种就是局部变量。

3.局部变量和全局变量的关系

当两个变量的名称相同时,当程序运行到代码块时,代码块中的那个变量——局部变量将会覆盖全局变量。当程序流程离开代码块时,局部变量过期,此时全局变量将再次可见。

4.自动变量和栈

其实函数调用的值在函数结束的时候,这些值并没有被删除,但不在被标记,它们占据的空间将被下一个将值加入到栈中的函数调用所使用。

5.静态持续变量

静态持续变量分为三种:静态、无链接性;静态,外部链接性;静态,内部链接性。
静态持续变量在整个程序执行期间一直存在。

1.外部链接性

静态外链不初始化默认值为0.
加了extern关键字的变量名不初始化为声明,系统不会重新为它分配内存空间,该文件的程序使用另外一个文件定义的同名变量占用的空间,有点类似于引用。
而不加extern关键字的变量如常规变量,不管初不初始化,系统都会为它分配内存空间。

2.内部链接性

将static限定符用于作用域为整个文件的变量时,该变量的链接性将为内部的。因此意味着该变量只能在定义的它的文件中使用。

3.无链接性

定义在代码块中的static变量,被称为无链接性的静态变量,这意味着该变量只能在该代码块中可用,但是它和自动持续变量不同的是,自动持续变量在函数结束时,系统自动释放它们的内存空间,但是无链接性的静态变量是一直存在的。

6.作用域解析运算符( :: )

放在变量名前面时,该运算符表示使用变量的全局版本。

7.命名空间的相关要点

using 声明:

using jill::a; //相当于在本区域内定义变量

using编译指令:

using namespace jill; //虽然在本区域定义,但却在全局起作用

using 声明。

#include <iostream>
using namespace std;
namespace Jill {
	float fetch = 1.0;
}
int main()
{
	using jill::fetch;
	//int a=3; 将出错,因为上面相当于是定义了a(重定义错误) 
	cout<<a<<endl;
	return 0;
}

但是

#include <iostream>
using namespace std;
namespace Jill {
	float fetch = 1.0;
}
using Jill::fetch;	//将Jill::fetch变为全局变量
int main()
{
	int fetch = 2;
	cout<<fetch<<endl;
	return 0;
}

此时输出的结果就是2,说明局部变量覆盖了全局变量

但是!

#include <iostream>
using namespace std;
namespace Jill {
	float fetch = 1.0;
}
using Jill::fetch;	//将Jill::fetch变为全局变量
int main()
{
	int fetch = 2;
	cout<<Jill::fetch<<endl;
	return 0;
}

此时输出的结果就是Jill命名空间中的fetch的值1。

using编译命令

#include <iostream>
using namespace std;
namespace Jill{
	int fetch = 3;
}
int main(){
	using namespace Jill;//虽在本区域,但却是全局 
	int fetch = 4;             //因此这里覆盖全局,不会出错 
	cout<<fetch<<endl;
	return 0;
}

这里输出结果为4,函数修改了命名空间中fetch的值,将其修改为4.
那么将using编译命令提到函数之外又会怎么样呢?

#include <iostream>
using namespace std;
namespace Jill{
	int fetch;
}
using namespace Jill;
int main(int argc, char *argv[]){
	int fetch=3;             //覆盖全局,不会出错 
	cout<<fetch<<endl;
	return 0;
}

此时的输出结果为3,因为局部变量覆盖了全局变量。

注意:使用using编译指令导入一个名称空间中所有的名称与使用多个using声明是不一样的,而更像是大量使用作用域解析操作符。

使用using声明时,就好像声明了相应的名称一样。如果某个名称已经在函数中声明了,则不能使用using声明导入相同的名称。

在上面的例子中,名称空间为全局的.如果使用using编译指令导入一个已经在函数中声明的名称,则局部名称将隐藏名称空间名,
(书上就这样模糊)

记住:

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

2.一般来说,使用using声明比使用using编译指令更安全,这是由于它只导入指定的名称。如果该名称与局部名称发生冲突,编译器将付出指示。using编译指令导入所有名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告,另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确的知道添加了哪些名称。

发布了22 篇原创文章 · 获赞 2 · 访问量 480

猜你喜欢

转载自blog.csdn.net/weixin_42709632/article/details/103949704