using namespace std 是什么意思——C++命名空间

目录

  • namespace命名空间
    • 局部域和全局域
    • namespace
      • 展开命名空间
      • 指定命名空间
    • 命名空间的嵌套
    • 不同文件中的同名命名空间
  • using namespace std 是什么意思

我们先看一段C代码:

#include 
#include 

int rand = 0;

int main()
{
	printf("%d", rand);
	return 0;
}

我们直接看可能不会发现问题,但是这段代码是运行不出来的
using namespace std 是什么意思——C++命名空间_第1张图片

原因就是rand名与stdlib.h库中的函数命冲突,所以运行不出来

命名冲突的发生有2个原因:
1.跟库中冲突
2.一个项目不同部分由不同人编写,最后合并时发生命名冲突

为了避免自己定义的变量名或函数命与库中的名冲突,于是在C++中引入了命名空间这一概念。


namespace命名空间

局部域和全局域

我们先了解一下 局部域全局域,在同一域中不可以创建2个同名变量,但在同一域中可以创建2个同名变量

下面在局部域和全局域建立2个同名变量

#include 

int a = 1;//全局域

int main()
{
	int a = 0;//局部域
	printf("%d\n", a);
	return 0;
}

那么在这里如果要输出a的值,那么输出的是全局域中的值还是局部域中的值呢?

答案是:输出局部域中的a
using namespace std 是什么意思——C++命名空间_第2张图片
所以可以得出一个结论:搜索范围是先局部域再全局域,默认是在局部域中搜索,如果没有局部域,再在全局域中搜索

如果想要输出全局域中的a怎么办呢?

使用::域作用限定符,::a就表示全局域中的a

#include 

int a = 1;//全局域

int main()
{
	int a = 0;//局部域
	printf("%d\n", ::a);
	return 0;
}

namespace

下面我们通过namespace创建一个命名空间域

namespace test
{
	int a = 2;
}

那么现在我们怎么输出这个命名空间域中的a呢?

C++中的搜索范围是:局部域->全局域,如果不展开命名空间或指定访问命名空间,是不会去命名空间中搜索的
只有展开命名空间或指定访问命名空间才会搜索到命名空间域中

可以看到,不展开命名空间也不指定访问命名空间,是不会输出命名空间域中的a

#include 
namespace test
{
	int a = 2;
}

//int a = 1;//全局域

int main()
{
	//int a = 0;//局部域
	printf("%d\n", ::a);
	return 0;
}

using namespace std 是什么意思——C++命名空间_第3张图片


展开命名空间

下面用using namespace test展开命名空间域

说明:这里展开的意思是编译器是否去域里进行搜索
#include本质不同,不要错误理解

#include 
namespace test
{
	int a = 2;
}
using namespace test;//展开命名空间域

int a = 1;//全局域

int main()
{
	int a = 0;//局部域
	printf("%d\n", a);
	return 0;
}

这时,三个域中的a是可以共存的,按照搜索顺序,这里会输出局部域中的a
这里如果删除掉全局域和局部域中的a,这里就会输出命名空间域中的a

如果去掉局部域中的a,展开命名空间域,此时在全局域和命名空间域中都有一个a,那么这时如果不使用::,会输出哪个a

#include 
namespace test
{
	int a = 2;
}
using namespace test;//展开命名空间域

int a = 1;//全局域

int main()
{
	//int a = 0;//局部域
	printf("%d\n", a);
	return 0;
}

答案是会发生命名冲突
using namespace std 是什么意思——C++命名空间_第4张图片

这是因为展开后就代表着里面的内容就暴露到全局,与原全局域中的a冲突

所以可以看出,using namespace不是特别好,using namespace的本意是为了防止冲突,但是展开后又会发生冲突

所以不要轻易的使用using namespace


指定命名空间

我们还可以通过展开命名空间的方法去搜索命名空间域中的a
也是使用域作用限定符::

printf("%d\n", a);//输出局部域中的a
printf("%d\n", ::a);//输出全局域中的a
printf("%d\n", test::a);//输出命名空间域中的a

这样,就不会发生任何冲突
所以,如果只想使用某个命名空间中的一两个函数或变量,指定命名空间就可以,没有必要展开整个命名空间


命名空间的嵌套

命名空间是支持嵌套的,因为如果我们把所有的变量、函数、结构都放在一个命名空间中时,也会不可避免的发生冲突

//命名空间的嵌套
namespace A1
{
	int aa = 10;
	namespace A2
	{
		int aa = 20;
	}
}

怎么去访问嵌套的命名空间中的元素呢?
多次使用::

printf("%d\n" ,A1::aa); //访问A1中的aa
printf("%d\n", A1::A2::aa);//访问被嵌套的A2中的aa

不同文件中的同名命名空间

在不同文件中的同名命名空间,最终会合并在一起

这里我们在2个不同的头文件中创建了同名命名空间
using namespace std 是什么意思——C++命名空间_第5张图片

到了源文件中,这2个命名空间就自动合并了

#include "A.h"
#include "B.h"


int main()
{
	std::cout << hhh::a << std::endl;
	std::cout << hhh::b << std::endl;

}

using namespace std 是什么意思

std是C++库的命名空间,std中包含了STL和C++库
using namespace std 是什么意思——C++命名空间_第6张图片

C++中常用的输入输出也都在std中,所以我们平常在创建cpp文件后都会第一时间把using namespace std写上

#include 
using namespace std;

int main()
{
	cout<<"hello"<<endl;
}

通过前面的内容,我们知道 直接展开会有风险,如果自己定义跟库重名,就会报错
所以在平时日常练习时可以展开,在一些项目中建议指定访问,不轻易展开命名空间

下面是通过指定访问实现输出:

#include 


int main()
{
	std::cout<<"hello"<<std::endl;
	std::cout<<"hello"<<std::endl;
	std::cout<<"hello"<<std::endl;
	std::cout<<"hello"<<std::endl;
}

在每一个cout和·endl前面都要加上std::,这么看起看来十分麻烦且枯燥,所以还有一种写法。就是将常用的展开

//将常用的展开
using std::cout;
using std::endl;

int main()
{
	cout << "hello" << endl;
}

这样写,即避免了直接展开命名空间的风险,也减少了写std的次数

你可能感兴趣的:(C++,c++,算法,c语言)