为什么尽量不要使用using namespace std?

作者:MacTvish
链接:http://www.zhihu.com/question/26911239/answer/51503880
来源:知乎

因为使用STL中 有部分名称是没有加下划线的保留标记的
而在自己的源代码中用到了后会引发未定义的后果

例如:
#include <algorithm>
using namespace std;
int main()
{
	int max=0;
}


一直我都告诫学习C++的人 以后精通了C++就不要用 using namespace std;
用例如 using std::cin;效果会更好


举个血淋淋的例子
在NOIP2014提高组比赛时 有个朋友因为用到了计数器 就用了count (全局声明using namespace std;)
本地编译(Dev-C++)通过 测试一切正常
但在提交答案之后 走出考场 谈论比赛过程时无意中提到count
我很惊讶 为何能编译通过 我以前在学校训练时用的C-free声明using namespace std;时用count会报错指出冲突
所以从那时候开始我在做题时就没有用过using编译指令 只用using声明
他一拍脑袋说忘了这个茬了但是后悔已经晚了
他那题由于编译未通过 0分只拿到了省三


----update:Jun 18th , 2015

看来论据不够充分 那我加下

《C++ Primer Plus (第六版 中文版 人民邮电出版社)》第九章:内存模型和名称空间 第328页:
"有关using编译命令和using声明,需要记住的一点是,他们 增加了名称冲突的可能性。"

《C++ Primer Plus (第六版 中文版 人民邮电出版社)》第九章:内存模型和名称空间 第329页:
一般说来, 使用using命令使用using编译命令安全,这是由于它 只导入了制定的名称。如果该名称与局部名称发生冲突,编译器 将发出指示。using编译命令导入所有的名称,包括可能并不需要的名称。如果与局部名称发生冲突,则 局部名称将覆盖名称空间版本,而编译器 并不会发出警告。另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。
...
然而名称空间的支持者希望有更多的选择,既可以使用解析运算符面也可以使用using声明,也就是说,不要这样做:
using namespace std; // avoid as too indiscriminate(随意)
而应这样做
int x;
std::cin >> x ;
std::cout << x << std::endl;
或者这样做
using std::cin;
using std::cout;
using std::endl;
int x;
cin >> x;
cout << x << endl;

《C++ Primer Plus (第六版 中文版 人民邮电出版社)》附录I: 转换为ISO标准的C++ 第915页:
名称空间有助于组织程序中使用标识符,避免名称冲突。由于标准库是使用性的头文件组织实现的,它将名称放在std名称空间中,因此使用这些头文件需要处理名称空间。
出于简化的目的,本书的事例通常使用编译命令using来使std名称空间中名称可用:
#include <iostream>
#include <string>
#include <vector>
using namespace std;    //a using-directive
然而, 不管需要于否,都导出名称空间中的所有名称,是于名称空间的初衷背道而驰的


由此可见 using namespace std; 并不是可以随意使用的编译命令。

----update:Jun 18th , 2015 night.

觉得例子还不够丰富 就上了google看看
在Steve Donovan 《C++ by Example》中写到:
However, some people feel strongly that using namespace std cases namespace pollution because everything is dumped into the global namespace, which is what namespaces were designed to prevent. You need to understand the implications of using namespace std,and you need to recognize that there is one case where it always a bad idea.

而在国外的论坛StackOverflow
对于 What requires me to declare “using namespace std;”?
Péter Török给出了这样的解释
However,
using namespace std;
is considered a bad practice because you are practically importing the whole standard namespace, thus opening up a lot of possibilities for name clashes. It is better to import only the stuff you are actually using in your code, like
using std::string;
<think>我们分析头文件和源文件的包含关系: 1. 头文件(.h)中通常只包含声明,不应该包含`using namespace std;`这样的指令,因为这会污染全局命名空间。 2. 源文件(.cpp)中可以使用`using namespace std;`,因为它的作用范围仅限于该编译单元。 问题:假如头文件里面没有用`using namespace std;`,而它对应的源文件使用了,那么main函数在包含该头文件时是否会包含`using namespace std;`? 答案:不会。 解释: 当我们在一个源文件(比如triangle.cpp)中使用了`using namespace std;`,它只在该源文件中有效。头文件(triangle.h)中不包含这个指令。当main.cpp包含头文件(#include "triangle.h")时,预处理器只是将头文件的内容插入到main.cpp中。由于头文件里没有`using namespace std;`,所以main.cpp中不会因为这个头文件而引入`using namespace std;`。 但是,需要注意的是,如果main.cpp自身使用了`using namespace std;`,那么它当然会生效,但这与头文件无关。 示例: 假设头文件triangle.h内容如下: ```cpp #ifndef TRIANGLE_H #define TRIANGLE_H #include <vector> class Triangle { // ... 声明 }; #endif ``` 对应的源文件triangle.cpp: ```cpp #include "triangle.h" #include <iostream> using namespace std; // 只在triangle.cpp中有效 void Triangle::someFunction() { cout << "Hello"; // 这里可以,因为triangle.cpp中有using namespace std; } ``` 现在,main.cpp: ```cpp #include "triangle.h" // 这里不会引入using namespace std; #include <iostream> int main() { // cout << "Hello"; // 如果这样写,必须使用std::cout,或者自己在main.cpp里使用using namespace std; std::cout << "Hello"; // 正确 return 0; } ``` 因此,main函数包含头文件时不会包含源文件中的`using namespace std;`。 重要原则: - 头文件中应避免使用`using namespace`,特别是避免在全局作用域中使用,因为多个头文件可能被包含,导致命名冲突。 - 在源文件中使用`using namespace`是相对安全的,只要它不会引起本编译单元内的命名冲突。 §§相关问题§§ 1. 为什么在C++头文件中使用`using namespace`被认为是不好的编程习惯? 2. 如何避免在头文件中使用`using namespace`的同时减少重复输入`std::`前缀? 3. 在多个源文件中使用相同的`using namespace`指令是否会导致链接错误? 4. 除了`using namespace std;`,还有哪些方式可以简化命名空间的使用? 5. 如果头文件被多个源文件包含,其中一个源文件使用了`using namespace std;`,是否会影响其他源文件的命名解析?</think>### 头文件与源文件的 `using namespace std` 作用域解析 #### 核心结论: **main函数包含头文件时,不会继承源文件中的 `using namespace std`**。原因如下: 1. **编译单元隔离性** 每个 `.cpp` 文件是独立的编译单元。`using namespace std` 仅在它所在的源文件(如 `triangle.cpp`)中生效,不会通过头文件传播。 2. **头文件包含机制** 当 `main.cpp` 包含头文件 `triangle.h` 时,预处理器仅复制头文件内容到 `main.cpp`,不会包含关联源文件(`triangle.cpp`)的任何内容。 --- ### 代码示例说明 ```cpp // triangle.h(头文件) #include <vector> // 不使用 using namespace std class Triangle { std::vector<float> data; // 明确使用 std:: }; ``` ```cpp // triangle.cpp(源文件) #include "triangle.h" using namespace std; // 仅在本文件有效 void Triangle::process() { vector<int> temp; // 此处可省略 std:: } ``` ```cpp // main.cpp(主程序) #include "triangle.h" // 仅包含头文件内容 int main() { std::vector<int> v1; // 必须使用 std:: // vector<int> v2; // 错误!未引入 std 命名空间 Triangle tri; // 正确,头文件未污染命名空间 } ``` --- ### 关键原理 | 文件类型 | `using namespace std` 影响范围 | 是否影响 main | |----------------|--------------------------------|---------------| | 头文件 (.h) | 所有包含该头文件的源文件 | ✔️ 是(应避免)| | 实现文件 (.cpp)| 仅当前编译单元 | ❌ 否 | > **最佳实践**: > 1. **头文件绝对避免** `using namespace` > 2. 源文件可局部使用(在函数内部或 .cpp 文件顶部) > 3. 优先使用显式限定(如 `std::vector`) --- ### 符号解析表 | 位置 | `vector` 是否有效 | 原因 | |------------------|-------------------|-------------------------------| | triangle.h | ❌ 必须用 `std::` | 头文件未引入命名空间 | | triangle.cpp | ✔️ 有效 | 当前文件已引入命名空间 | | main.cpp | ❌ 无效 | 未引入且头文件未传播命名空间 |
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值