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

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

我们先看一段C代码:


#include <stdio.h>
#include <stdlib.h>
int rand = 0;
int main()
{
  printf("%d", rand);
  return 0;
}
1


我们直接看可能不会发现问题,但是这段代码是运行不出来的

15fdf419f9544435b33fd8dfaaf8f8ac.png


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


命名冲突的发生有2个原因:

1.跟库中冲突

2.一个项目不同部分由不同人编写,最后合并时发生命名冲突


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


namespace命名空间

局部域和全局域

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


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


#include <iostream>
int a = 1;//全局域
int main()
{
  int a = 0;//局部域
  printf("%d\n", a);
  return 0;
}


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


答案是:输出局部域中的a值


6bc80d41780142baa3be54d40106c46c.png





所以可以得出一个结论:搜索范围是先局部域再全局域,默认是在局部域中搜索,如果没有局部域,再在全局域中搜索


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


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


#include <iostream>
int a = 1;//全局域
int main()
{
  int a = 0;//局部域
  printf("%d\n", ::a);
  return 0;


10

namespace

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


namespace test
{
  int a = 2;
}


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


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

只有展开命名空间或指定访问命名空间才会搜索到命名空间域中


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


#include <iostream>
namespace test
{
  int a = 2;
}
//int a = 1;//全局域
int main()
{
  //int a = 0;//局部域
  printf("%d\n", ::a);
  return 0;
}





1e4a3bbeda364617b47326408ab0791b.png



展开命名空间

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


说明:这里展开的意思是编译器是否去域里进行搜索

与#include本质不同,不要错误理解


#include <iostream>
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 <iostream>
namespace test
{
  int a = 2;
}
using namespace test;//展开命名空间域
int a = 1;//全局域
int main()
{
  //int a = 0;//局部域
  printf("%d\n", a);
  return 0;
}

5

答案是会发生命名冲突


d9ac1df52f074f8dbf90ca859cddac77.png







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


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


所以不要轻易的使用using namespace


指定命名空间

我们还可以通过展开命名空间的方法去搜索命名空间域中的a

也是使用域作用限定符::

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


这样,就不会发生任何冲突

所以,如果只想使用某个命名空间中的一两个函数或变量,指定命名空间就可以,没有必要展开整个命名空间


命名空间的嵌套

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


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


9

怎么去访问嵌套的命名空间中的元素呢?

多次使用::


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

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

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


这里我们在2个不同的头文件中创建了同名命名空间




f846a57a5d0b4d85a538e783a7e8bc5c.png



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

#include "A.h"
#include "B.h"
int main()
{
  std::cout << hhh::a << std::endl;
  std::cout << hhh::b << std::endl;
}
1


using namespace std 是什么意思

std是C++库的命名空间,std中包含了STL和C++库




c81aa6307f5a42d1b2367dedd030dca1.png



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


#include <iostream>
using namespace std;
int main()
{
  cout<<"hello"<<endl;
}

的内容,我们知道 直接展开会有风险,如果自己定义跟库重名,就会报错

所以在平时日常练习时可以展开,在一些项目中建议指定访问,不轻易展开命名空间


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


#include <iostream>
int main()
{
  std::cout<<"hello"<<std::endl;
  std::cout<<"hello"<<std::endl;
  std::cout<<"hello"<<std::endl;
  std::cout<<"hello"<<std::endl;
}
1


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

//将常用的展开
using std::cout;
using std::endl;
int main()
{
  cout << "hello" << endl;
}
目录
相关文章
|
3月前
|
存储 前端开发 安全
C++一分钟之-未来与承诺:std::future与std::promise
【6月更文挑战第27天】`std::future`和`std::promise`是C++异步编程的关键工具,用于处理未完成任务的结果。`future`代表异步任务的结果容器,可阻塞等待或检查结果是否就绪;`promise`用于设置`future`的值,允许多线程间通信。常见问题包括异常安全、多重获取、线程同步和未检查状态。解决办法涉及智能指针管理、明确获取时机、确保线程安全以及检查未来状态。示例展示了使用`std::async`和`future`执行异步任务并获取结果。
50 2
|
6天前
|
安全 C++
C++: std::once_flag 和 std::call_once
`std::once_flag` 和 `std::call_once` 是 C++11 引入的同步原语,确保某个函数在多线程环境中仅执行一次。
|
21天前
|
程序员 C++ 开发者
C++命名空间揭秘:一招解决全局冲突,让你的代码模块化战斗值飙升!
【8月更文挑战第22天】在C++中,命名空间是解决命名冲突的关键机制,它帮助开发者组织代码并提升可维护性。本文通过一个图形库开发案例,展示了如何利用命名空间避免圆形和矩形类间的命名冲突。通过定义和实现这些类,并在主函数中使用命名空间创建对象及调用方法,我们不仅解决了冲突问题,还提高了代码的模块化程度和组织结构。这为实际项目开发提供了宝贵的参考经验。
38 2
|
8天前
|
C语言 C++
C++(六)Namespace 命名空间
命名空间(Namespace)是为了解决大型项目中命名冲突而引入的机制。在多库集成时,不同类库可能包含同名函数或变量,导致冲突。C++通过语法形式定义了全局无名命名空间,并允许对全局函数和变量进行作用域划分。命名空间支持嵌套与合并,便于协同开发。其使用需谨慎处理同名冲突。
|
1月前
|
编译器 C语言 C++
C++入门 | 命名空间、输入输出、缺省参数
C++入门 | 命名空间、输入输出、缺省参数
33 4
|
2月前
|
存储 C++ 运维
开发与运维函数问题之使用C++标准库中的std::function来简化回调函数的使用如何解决
开发与运维函数问题之使用C++标准库中的std::function来简化回调函数的使用如何解决
37 6
|
2月前
|
C++ 运维
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
44 2
|
2月前
|
C++
C++一分钟之-类型别名与using声明
【7月更文挑战第20天】在C++中,类型别名和`using`声明提升代码清晰度与管理。类型别名简化复杂类型,如`using ComplexType = std::vector&lt;std::shared_ptr&lt;int&gt;&gt;;`,需注意命名清晰与适度使用。`using`声明引入命名空间成员,避免`using namespace std;`全局污染,宜局部与具体引入,如`using math::pi;`。恰当应用增强代码质量,规避常见陷阱。
51 5
|
2月前
|
安全 编译器 C++
C++一分钟之-C++中的属性命名空间
【7月更文挑战第22天】C++11引入属性作为元数据,虽无内置属性命名空间,但可通过自定义属性与命名空间组合实现类似效果。例如,创建`perf`命名空间存放`slow`和`fast`属性来标记函数性能。正确使用属性需注意位置、避免重复和确保与实现一致,以提升代码可读性和编译器理解。通过模拟属性命名空间,可以更有效地管理和使用属性。
40 1
|
2月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开