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


当前回答

不应该在全局范围内使用using指令,尤其是在头中。但是,在某些情况下,即使是在头文件中,也会出现这种情况:

template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
    using namespace std; // No problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}

这比显式限定(std::sin,std::cos…)更好,因为它更短,并且能够处理用户定义的浮点类型(通过依赖于参数的查找(ADL))。

其他回答

老实说,对我来说,这就像讨论缩进空间的数量。

在标头中使用指令会导致损坏。但是在C++文件中呢?如果同时使用两个名称空间,可能会发生这种情况。但如果你使用一个,它更多的是风格而不是真正的效率。

你知道为什么关于缩进的线索如此流行吗?任何人都可以说些什么,听起来非常聪明和有经验。

对于不合格的导入标识符,您需要像grep这样的外部搜索工具来查找标识符的声明位置。这使得关于程序正确性的推理更加困难。

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

短版本:不要在头文件中使用全局using声明或指令。可以在实现文件中使用它们。以下是Herb Sutter和Andrei Alexandrescu在C++编码标准中对这个问题的看法(我用粗体强调):

总结命名空间using是为了方便您,而不是为了强加给他人:不要在#include指令之前编写using声明或using指令。推论:在头文件中,不要使用指令或声明编写命名空间级别;相反,显式命名空间限定所有名称。(第二条规则与第一条规则相同,因为标头永远无法知道后面可能出现的其他标头#includes。)讨论简而言之:在#include指令之后,你可以也应该在你的实现文件中自由地使用命名空间使用声明和指令,并对此感到满意。尽管重复了相反的断言,但使用命名空间的声明和指令并不是邪恶的,它们不会破坏命名空间的目的。相反,它们使名称空间可用。

我同意其他人的看法——这是在要求名字冲突、歧义,但事实是它不够明确。虽然我可以看到使用的用途,但我个人倾向于限制它。我也会强烈考虑其他人所指出的:

如果你想找到一个可能是一个相当常见的名称的函数名,但你只想在std命名空间中找到它(或者反过来——你想更改所有不在命名空间std、命名空间X…中的调用),那么你打算怎么做?

你可以编写一个程序来完成它,但花时间在项目本身上而不是编写一个维护项目的程序,这不是更好吗?

就我个人而言,我其实并不介意std::前缀。我更喜欢它的外观而不是没有它。我不知道这是因为它很明确,并对我说“这不是我的代码……我正在使用标准库”,还是因为它是其他东西,但我觉得它看起来更好。这可能很奇怪,因为我最近才接触C++(使用C和其他语言的时间更长,而且C是我一直以来最喜欢的语言,就在汇编语言之上)。

还有一件事,尽管它与上述内容和其他人指出的内容有些关联。虽然这可能是不好的做法,但我有时会为标准库版本保留std::name,为特定于程序的实现保留名称。是的,这确实会咬你,咬你很厉害,但归根结底,我是从零开始这个项目的,我是唯一的程序员。例如:我重载std::string并将其称为string。我有一些有用的补充。我之所以这样做,部分原因是我的C和Unix(+Linux)倾向于小写名称。

除此之外,还可以使用命名空间别名。这里是一个可能没有提到的有用的例子。我使用C++11标准,特别是libstdc++。它没有完全的std::regex支持。当然,它可以编译,但它会抛出一个异常,这是程序员端的错误。但它缺乏实施。

下面是我解决这个问题的方法。安装Boost的正则表达式,并将其链接进来。然后,我执行以下操作,以便在libstdc++完全实现它时,我只需删除这个块,代码保持不变:

namespace std
{
    using boost::regex;
    using boost::regex_error;
    using boost::regex_replace;
    using boost::regex_search;
    using boost::regex_match;
    using boost::smatch;
    namespace regex_constants = boost::regex_constants;
}

我不会争论这是不是个坏主意。然而,我会争辩说,它为我的项目保持了干净,同时又使它变得具体:没错,我必须使用Boost,但我使用它就像libstdc++最终会使用它一样。是的,启动自己的项目并从一开始就使用标准(…)对帮助维护、开发和项目所涉及的一切都有很大的帮助!

只是想澄清一下:我实际上并不认为在STL中使用类名或其他名称来代替它是一个好主意。字符串对我来说是个例外(忽略第一个,上面的,或者这里的第二个,如果必须的话双关语),因为我不喜欢“字符串”这个概念。

事实上,我仍然非常倾向于C和C++。省略细节,我所做的很多工作更适合C(但这是一个很好的练习,也是让自己学会另一种语言的好方法)。不要对对象/类等抱有偏见,这可能更好地表述为不那么封闭、不那么傲慢、更容易接受。)。但有用的是一些人已经提出的建议:我确实使用了列表(它相当通用,不是吗?),并排序(相同的事情)以命名两个,如果我使用名称空间std;,因此,为了达到这个目的,我更喜欢具体、可控,并且知道如果我打算将其作为标准用途,那么我必须指定它。简单地说:不允许假设。

至于让Boost的正则表达式成为标准的一部分。我这样做是为了将来的集成,而且——再次,我完全承认这是偏见——我不认为它像Boost::正则表达式::。。。。事实上,这对我来说是另一回事。C++中有很多东西我还没有完全接受,包括外观和方法(另一个例子:varadic模板与var参数[尽管我承认varadic模版非常有用!])。即使那些我确实接受的人也很困难,我仍然对他们有意见。