using namespace std

整体认识 —— 解决命名冲突

一个简单的C++程序:

#include<iostream>
 
using namespace std;
 
int main(int argc,char **argv)
{
	cout<<"hello world !"<<endl;
	system("pause");    // 让程序暂停,按任意键继续 注意,这行不是标准的C++代码, 仅限于调试使用 
	cout<<"出来了"<<endl;
	return 0;
}

其中:

using namespace std;

是什么意思,又有什么作用呢?

“using namespace std;”,顾名思义 —— 使用(using)名空间(namespace)std,std是名空间的名字,这是C++为了解决不同工程的变量,函数等命名冲突的问题,引入的名空间(namespace)的概念,相当于文件夹的目录和子文件的关系——不同的目录(namespce)下即使有相同子文件名(变量,函数等)也不会产生冲突(如果接触过Java,这里类似于Java中不同的包的作用)。下面是个小例子:

// 声明名空间Jack
namespace Jack {
  double height;
  void fetch();
}
// 声明名空间Jill
namespace Jill {
  double height;
  void fetch();
}
// 使用名空间
cout<<Jack::height<<endl;
cout<<Jill::height<<endl;
Jack::fetch();

可以看到,可以指定特定名空间下的同名变量(height)和函数(fetch())。

有时名空间内的内容太多,使用限定符::就太过繁琐,可以使用"using namespace XXX;"直接引入整个名空间:

namespace Jack {
  double height;
  void fetch();
  ...
}

 
int main(int argc,char **argv)
{
    // 这句之后的代码,如果出现Jack中的变量,函数等,均视为Jack中的
    // 类似于局部变量覆盖整体变量的效果
    using namespace Jack;   
    
    height= 176.34;
    fetch();
}

使用方式

注意两种用法的区别:

限定符方式: Jack::height;

using编译方式:using namespace Jack;

前者可以看做只引用名空间Jack中的一个变量——height,后者是编译整个名空间Jack。

显然,表面来看,”using namespace Jack;“无脑又方便,那为什么还要用限定符呢?

这是因为”using namespace Jack;“会编译整个名空间并引入到当前程序中,如果本地有变量方法和类名如果和其冲突,则本地会覆盖原名空间的内容,看下面的例子:

#include<iostream>

using namespace std; 

namespace Senario
{
   class Student
 {
     int age;
     string name;
     string sex;
     Student()
     {
       age = 20;
       name = "Martin";
       sex = "male";
     }
 };
}    // namespace Senario的作用域到此结束


// 注意这里是在当前名空间内声明的Student
 class Student
  {
     int age;
     string name;
     Student()
     {
       age = 18;
       name = "Kevin";
     }
  };


int main(int argcs,char** args)
{
  using namespace Senario;

  // 此时这个Student就会被“局部变量”————当前名空间内Student覆盖掉
  Student student = new Student();   
  cout<<student.name<<endl;
  cout<<student.sex<<endl;
  return 0;
}

程序编译结果:

好吧,经实验,直接报错:

[Error] reference to 'Student' is ambiguous

①处说的很清楚,Student是不明确的,②处给出了更详细的信息:Student有两个选择:class Student(当前名空间内)和Senario:: Student两个选择。

总结

现在回到原来的问题:

using namespace std;

其实已经很清晰,std是CPP标准库所在的名空间的名称,"using namespace std;"的作用——引入并编译了标准库中所有的内容,其中最重要的莫过于cin,cout,endl,string。

使用using编译指令固然方便,但是就像上面描述的问题一样,若程序中程序员自己定义的变量,方法,类等名称和std中冲突(这种情况下程序员大概率还不知道(std库太大,其中内容太多)),编译时就会报错。

所以”using namespace std;“虽然最常使用,但是也要注意:保证本地名空间和引入的其他名空间没有std相同的变量方法名(当然,在程序中没有调用的变量方法不影响)。

所以,总结一下:

最保险:

int main(int argcs,char** args)
{
int x;
std::cin >> x;
std::cout << x << std::endl;
}

偷懒但有隐患:

using namespace std;
int main(int argcs,char** args)
{
int x;
cin >> x;
cout << x << endl;
}

为避免冲突和提高效率(次要):

using std::cin;
using std::cout;
using std::endl;
int main(int argcs,char** args)
{
int x;
cin >> x;
cout << x << endl;
}

局部代码块中使用,引入名空间而不是头部引入:


int main(int argcs,char** args)
{

{
using namespace std;
int x;
cin >> x;
cout << x << endl;
}

...          //其他不需要用到std的代码

}

对于这种方式,可以像上面写的一样,使用花括号限定名空间作用域。

但这仅限于个别调用的场景,像cin,cout,endl,string基本散布在代码各个地方,这种方法就不行了,不过cin,cout,endl,string这样如此”常见“的标识符,甚至是个写C++的都知道,本地代码的命名应该不会与此发生冲突,故对于只使用std中cin,cout,endl,string的场景,使用using namespace std这种方式是安全且方便的。

当然,最保险的方式还是:

using std::cin;
using std::cout;
using std::endl;
using std::string;

另外,明白名空间的作用以后,可以将特定变量放在名空间中,如C++不提倡使用类似于static int counter这种来计数,那么可以将计数器放在特定的名空间中,每次访问加上名空间和作用符即可,这样既起到全局变量的效果,又不至于破坏程序的独立性和模块化。

喜欢的别忘了点个赞哦

参考资料:

https://www.jianshu.com/p/16141adf0229

https://www.jb51.net/article/129644.htm

声明:除已注明的引用外,文章系作者原创,引用转载请注明出处,如有必要请联系作者。

  • 22
    点赞
  • 0
    评论
  • 43
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值