我听说过使用名称空间std;这是不好的做法,我应该直接使用std::cout和std::cin。这是为什么?声明与std命名空间中的某个变量同名的变量是否有风险?


当前回答

同时使用多个命名空间显然是一个灾难,但在我看来,使用JUST命名空间std和仅使用命名空间std并不是什么大问题,因为重新定义只能由您自己的代码进行。。。

因此,只需将它们的函数视为保留名称,如“int”或“class”即可。

人们不应该对此如此吹毛求疵。你的老师一直都是对的。只需使用一个名称空间;这就是首先使用名称空间的全部意义。您不应该同时使用多个。除非它是你自己的。因此,再次定义不会发生。

其他回答

这是一种糟糕的做法,通常被称为全局命名空间污染。当多个名称空间具有相同的函数名和签名时,可能会出现问题,那么编译器决定调用哪个名称空间是不明确的,当您使用std::cout这样的函数调用指定名称空间时,这一切都可以避免。希望这有帮助。:)

另一个原因是惊讶。

如果我看到cout<<blah,而不是std::cout<<blah,我会想:这是什么cout?这是正常的服装吗?有什么特别的吗?

命名空间是命名作用域。命名空间用于对相关声明进行分组并保持独立项目分开。例如,两个单独开发的库可以使用相同的名称来表示不同的项,但用户仍然可以同时使用这两个:

namespace Mylib{
    template<class T> class Stack{ /* ... */ };
    // ...
}

namespace Yourlib{
    class Stack{ /* ... */ };
    // ...
}

void f(int max) {
    Mylib::Stack<int> s1(max); // Use my stack
    Yourlib::Stack    s2(max); // Use your stack
    // ...
}

重复名称空间名称可能会分散读者和作者的注意力。因此,有可能声明来自特定命名空间的名称在没有明确限定的情况下可用。例如:

void f(int max) {
    using namespace Mylib; // Make names from Mylib accessible
    Stack<int> s1(max); // Use my stack
    Yourlib::Stack s2(max); // Use your stack
    // ...
}

命名空间为管理不同库和不同版本的代码提供了强大的工具。特别是,它们为程序员提供了如何明确引用非本地名称的备选方案。

来源:C++编程语言概述作者:Bjarne Stroustrup

这可能比Greg写的更糟!

Library Foo 2.0可能会引入一个函数Qux(),它无疑比多年来代码调用的bar::Qux)更适合您对Qux的某些调用。然后你的代码仍然可以编译,但它会默默地调用错误的函数,上帝知道会发生什么。这是最糟糕的事情了。

请记住,std名称空间有大量的标识符,其中许多是非常常见的标识符(例如列表、排序、字符串、迭代器等),这些标识符也很可能出现在其他代码中。

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


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

在十年内,该项目发展到拥有数百万行代码。由于这些讨论一次又一次出现,我一度很好奇项目中实际使用(允许)函数范围的频率。我查阅了它的来源,只找到了一两打使用它的地方。对我来说,这表明,一旦尝试过,即使在允许使用std::的地方,开发人员也不会觉得每100kLoC使用一次指令就足够痛苦。


一句话:明确地给每件事加上前缀不会造成任何伤害,只需要很少的时间就可以习惯,而且有客观的优势。特别是,它使编译器和人类读者更容易解释代码,这可能是编写代码时的主要目标。

我不认为这在任何情况下都是不好的做法,但在使用它时都需要小心。如果你正在编写一个库,你可能应该在命名空间中使用作用域解析运算符,以防止你的库与其他库冲突。对于应用程序级代码,我看不出它有什么问题。