协慌网

登录 贡献 社区

为什么 “使用命名空间 std” 被认为是不好的做法?

其他人告诉我,在代码中using namespace std编写是错误的,我应该直接使用std::coutstd::cin

为什么using namespace std被视为不好的做法?是否效率低或者是否存在声明模糊变量(与std命名空间中的函数具有相同名称的变量)的风险?它会影响性能吗?

答案

这根本与性能无关。但请考虑一下:您正在使用两个名为 Foo 和 Bar 的库:

using namespace foo;
using namespace bar;

一切正常,你可以Quux()从 Bar 和 Foo 调用Blah() 。但是有一天你升级到新版本的 Foo 2.0,它现在提供了一个名为Quux()的函数。现在你遇到了冲突:Foo 2.0 和 Bar 都将Quux()导入你的全局命名空间。这将需要一些努力来修复,特别是如果函数参数碰巧匹配。

如果你曾经使用过foo::Blah()bar::Quux() ,那么引入foo::Quux()将是一个非事件。

我同意格雷格所写的一切,但我想补充一点: 它甚至可能比格雷格说的更糟糕!

Library Foo 2.0 可以引入一个函数Quux() ,这个函数明确地比你的Quux()调用更好,而不是你的代码多年来调用的bar::Quux() 。然后你的代码仍然编译 ,但它默默地调用错误的函数并且知道神知道什么。事情就像事情一样糟糕。

请记住, std命名空间有很多标识符,其中很多都是非常常见的(思想listsortstringiterator等),它们很可能也出现在其他代码中。

如果你认为这不太可能:在我给出这个答案大约半年之后,在 Stack Overflow 上有一个问题 ,其中几乎发生了这种情况(由于省略了std::前缀而导致错误的函数被调用)。 是另一个最近这样一个问题的例子。所以这是一个真正的问题。


这里还有一个数据点:很多年前,我还常常发现它必须在标准库中加入std::前缀。然后我在一个项目中工作,在开始时决定除了函数范围之外禁止using指令和声明。你猜怎么了?我们大部分时间都花了很长时间才习惯编写前缀,经过几周后,我们大多数人甚至同意它实际上使代码更具可读性 。这是有原因的: 你喜欢更短或更长的散文是主观的,但前缀客观上增加了代码的清晰度。不仅是编译器,而且您也发现更容易看到引用了哪个标识符。

十年来,该项目增长了数百万行代码。由于这些讨论一次又一次地出现,我曾经很好奇在项目中using (允许)实际使用的功能范围的频率。我找到它的来源,只找到了一两个地方使用它。对我而言,这表明,一旦尝试过,开发人员即使在允许使用指令的情况下,即使每 100kLoC 使用指令也不会发现std:: painful。


底线:明确地为所有内容添加前缀不会造成任何伤害,很少习惯,并具有客观优势。特别是,它使编码器和人类读者更容易理解代码 - 这应该是编写代码时的主要目标。

我认为把它放在你的类的头文件中是很糟糕的:因为那样你就会强迫任何想要使用你的类(通过包含你的头文件)也可以 '使用'(即看到所有内容)这些其他命名空间。

但是,您可以随意在(私有)* .cpp 文件中放置 using 语句。


请注意,有些人不同意我的说法 “感觉自由”,因为虽然 cpp 文件中的 using 语句比标题中的更好 (因为它不会影响包含头文件的人),但他们认为它仍然存在不好 (因为根据代码,它可能使类的实现更难维护)。 这个 FAQ 主题说,

using-directive 存在于遗留 C ++ 代码中,并且可以简化向命名空间的转换,但您可能不应该定期使用它,至少不应该在新的 C ++ 代码中使用它。

它提出了两种选择:

  • 使用声明:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • 克服它,只需键入 std ::

    std::cout << "Values:";