我听说using namespace std;
是不好的做法,应该直接使用std::cout
和std::cin
。这是为什么呢?是否会冒险声明与 std
命名空间中某些东西同名的变量?
我听说using namespace std;
是不好的做法,应该直接使用std::cout
和std::cin
。这是为什么呢?是否会冒险声明与 std
命名空间中某些东西同名的变量?
<algorithm>
中获取的函数),因此想象这些人可靠地避免使用这些标识符有些牵强。 看看你自己的代码,告诉我你是否从未使用过变量或函数名为 count
、distance
、log
、destroy
、launch
、visit
、beta
、sample
、messages
、clamp
、erase
、copy
、modulus
、left
等等。更不用说所有尚未在C++35发布时添加到std
中的标识符,这些标识符会破坏你的代码...... - Toby Speightusing namespace std;
?原因 1:避免名称冲突。
C++ 标准库庞大且不断扩展,C++ 中的命名空间用于减少名称冲突。当你使用 "using namespace std;" 时,你会整体导入所有内容。
这就是为什么在任何专业代码中都不会出现 "using namespace std;"。
原因 2:编译失败。
因为它将 std 命名空间中定义的数百个内容(类、方法、常量、模板等)引入到全局命名空间中。并且不仅仅是对写有 "using namespace std" 的文件有效,还会递归地对包含该文件的任何文件有效。这很容易导致意外的ODR违规和难以调试的编译器/链接器错误。
示例:
当你在全局命名空间中声明函数 "max" 时,你使用了 std 命名空间。
由于没有使用 cmath 头文件,一切似乎工作正常。
当其他人包含你的文件并使用cmath头文件时,他们的代码意外地无法构建,因为全局命名空间中有两个名为"max"的函数。使用 namespace std
的代码
#include <iostream>
#include <algorithm>
using namespace std;
int swap = 0;
int main() {
cout << swap << endl; // ERROR: reference to "swap" is ambiguous
}
没有 命名空间
#include <iostream>
int main() {
using std::cout; // This only affects the current function
cout << "Hello" <<'\n';
}
但是你可以使用 if,
如果你想制作简短的教程或程序等,可以使用。
如果你在源文件中频繁使用命名空间,并且确定不会发生冲突,那么使用 "using namespace std" 是没有问题的。
std::size_t
、std::cout
等元素可以通过 using namespace std;
更加便捷 — 我希望你不需要说服,让这样的指令出现在头文件中毫无意义!然而,对于翻译单元内的情况,你可能会心动……std
命名空间的类型、类等也在增加。如果您放松了对 std::
的限定,潜在的歧义就太多了。对于经常使用的 std
中的名称,比如 using std::fprintf;
或更可能的是 using std::size_t;
,放松限定符是完全合理的,但除非它们已经是语言(或特别是 C 库的 std
封装)的众所周知的部分,否则请使用限定符。typedef
,结合 auto
和 decltype
推断时,从可读性 / 可维护性的角度来看,实际上没有任何收益。#include <iostream>
using namespace std;
int main() {
// There used to be
// int left, right;
// But not anymore
if (left != right)
std::cout << "Excuse me, WHAT?!\n";
}
是的,命名空间很重要。在我的项目中,有一次我需要将一个变量声明引入到我的源代码中,但编译时它与另一个第三方库发生了冲突。
最终,我不得不通过其他方式来解决这个问题,使代码变得不太清晰。
说实话,对我来说,这就像讨论缩进空格的数量一样无关紧要。
在头文件中使用指令会造成损害。但是在C++文件中呢?也许如果您同时使用两个命名空间。但是,如果只使用一个命名空间,它更多的是关于风格而不是真正的效率。
你知道为什么有关缩进的主题如此受欢迎吗?任何人都可以对其发表评论,并听起来非常聪明和有经验。
if (left != right)
在使用 using std::namespace;
编译时不需要在代码中存在任何 left
或 right
。这是我在重构一个真实项目时遇到的一个真正的错误。std
中有很多常见的名称,这样的错误在许多商业代码库中仍然存在,其中原始值被分解,现在无效的用法仍然存在。这是一个 .cpp
源文件中的问题,而不是头文件中的问题。这不是一个观点问题。只要找到一个常见的例子,沉默的错误就会出现,游戏结束。禁止这种东西。 - Kuba hasn't forgotten Monica命名空间是为了避免命名冲突。C++ 基于 C,而 C 在函数和变量名称方面存在很多问题,因为有时来自不同库的函数会发生冲突。因此,库开发人员开始使用库名称作为前缀来定义它们的函数,例如以下示例:
foo/foo.h
:
void libfoo_foo_foo_h_open(); // the name can be weird then even this one!
C++引入了命名空间来轻松解决这个问题。
假设您有两个库,一个叫做file
,处理文件,另一个叫做window
,处理窗口,并且以下代码:
#include <file.h>
#include <window.h>
using namespace file;
using namespace window;
void open() {
...
}
file.h
:
namespace file {
void open(); // What!
}
window.h
:
namespace window {
void open(); // Oh no!
}
上述代码肯定会编译失败。
如果你不喜欢输入 std:: (只有 5 个字符),你总是可以这样做:(不适用于头文件)
using s = std;
using namespace std;
,那么你就是在邀请问题的发生,并且我必须问你一个问题:“名称空间的目的是什么?”using namespace std;
可能会导致名称冲突的问题:
无法在C++中定义全局变量
在这个例子中,一个非常通用的算法名(std::count
)与一个非常合理的变量名(count
)发生了名称冲突。为什么使用命名空间Std?
C++有一个标准库,其中包含在构建应用程序时使用的常见功能,如容器、算法等。如果这些名称是公开的,例如,如果它们在全局范围内定义了一个队列类,那么您将永远无法再次使用相同的名称而不会发生冲突。因此,他们创建了一个命名空间std来包含这种变化。
不使用的原因1: 不良实践
通常认为使用语句using namespace std是不良实践。替代这个声明的方法是每次我们声明一个类型时使用作用域运算符(::)指定标识符所属的命名空间。虽然该语句可以使我们在访问std命名空间中定义的类或类型时无需键入std::,但它会将整个std命名空间导入程序的当前命名空间。
不使用的原因2:编译器会混淆
在玩具程序中导入整个std库是可以的,但在生产级别的代码中,这是不好的。使用语句using namespace std; 会使std命名空间中声明的每个符号都可以在没有命名空间限定符的情况下访问。
例如:
现在,假设您升级到了新版本的C++,并且有更多新的std命名空间符号注入到您的程序中,而您对此一无所知。您可能已经在程序中使用了这些符号。现在编译器将很难确定声明的符号是属于您自己的实现还是从您导入的命名空间中而来。有些编译器会抛出错误。如果你运气不好,编译器选择了错误的实现并进行编译,那么肯定会导致运行时崩溃。
using
命令,除非针对特定的命名空间,例如std::literals::chrono_literals
、Poco::Data:Keywords
、Poco::Units
等与字面值或可读性技巧有关的内容。无论是在头文件还是实现文件中都不应该使用。在函数作用域内可能还可以接受,但除了字面值和相关内容外都没有用处。 - Ludovic Zenohate Lagouardette