我听说过使用名称空间std;这是不好的做法,我应该直接使用std::cout和std::cin。这是为什么?声明与std命名空间中的某个变量同名的变量是否有风险?
当前回答
这里有一个我在其他答案中都没有找到的观点:只使用一个名称空间。根据大多数答案,命名空间不好的主要原因是,你可能会有冲突的函数名,这会导致一片混乱。但是,如果只使用一个名称空间,则不会发生这种情况。确定您将使用最多的库(可能使用名称空间std;)并坚持使用它。
可以认为它有一个不可见的库前缀-std::vector变成了vector。在我看来,这是两全其美的:一方面,它减少了必须进行的键入(正如名称空间所预期的那样),另一方面,为了清晰和安全,它仍然需要使用前缀。如果有一个函数或对象没有名称空间前缀,那么您知道它来自您声明的一个名称空间。
请记住,如果您决定在全球范围内使用一个,请不要在本地使用其他。这又回到了其他答案,即本地名称空间通常比全局名称空间更有用,因为它们提供了各种便利。
其他回答
这是个案。我们希望在软件的生命周期内最大限度地降低软件的“总拥有成本”。声明“using namespace std”有一定的代价,但不使用它也有易读性的代价。
人们正确地指出,当使用它时,当标准库引入新的符号和定义时,您的代码将停止编译,您可能被迫重命名变量。然而,这可能是一个很好的长期目标,因为如果您出于某种令人惊讶的目的使用关键字,未来的维护人员将暂时感到困惑或分心。
你不希望有一个名为vector的模板,比如说,它不是其他人都知道的向量。因此,C++库中引入的新定义的数量非常少,可能根本找不到。必须进行这种更改是有代价的,但代价并不高,而且通过不将std符号名称用于其他目的而获得的清晰性来抵消。
考虑到类、变量和函数的数量,在每一个上声明std::可能会使代码出错50%,并使您更难理解。一个算法或方法中的一个步骤可以在一屏代码上执行,现在需要前后滚动才能执行。这是一个真实的成本。可以说,这可能不是一个高成本,但那些否认它存在的人是缺乏经验的、教条的,或者根本就是错误的。
我提供以下规则:
std不同于所有其他库。这是每个人基本上都需要知道的一个库,在我看来,最好将其视为语言的一部分。一般来说,使用命名空间std是一个很好的例子,即使没有其他库。永远不要通过将此using放在头中来迫使编译单元(.cpp文件)的作者做出决定。始终将决定权交给编译单元的作者。即使在一个决定在任何地方使用名称空间std的项目中,也可能会有一些模块作为该规则的例外处理。尽管名称空间功能允许您有许多定义相同符号的模块,但这样做会令人困惑。请尽可能保持名称不同。即使不使用名称空间特性,如果您有一个名为foo的类,并且std引入了一个名foo的类型,那么长期来说重命名您的类可能会更好。使用名称空间的另一种方法是通过前缀手动命名符号。我有两个库,我用了几十年,实际上都是从C库开始的,每个符号的前缀都是“AK”或“SCWin”。一般来说,这就像避免使用“using”构造,但不使用双冒号。AK::foo()改为AKFoo()。它使代码更密集5-10%,更不冗长,唯一的缺点是,如果必须使用两个具有相同前缀的这样的库,则会遇到很大的麻烦。注意,X Window库在这方面非常出色,只是它们忘记了使用一些#定义:TRUE和FALSE应该是XTRUE和XFALSE,这与Sybase或Oracle产生了命名空间冲突,它们同样使用了TRUE和FALSE,但值不同!(在数据库的情况下为ASCII 0和1!)这样做的一个特殊优点是,它似乎适用于预处理器定义,而C++使用/命名空间系统不处理它们。这样做的一个好处是,它提供了从项目的一部分到最终成为图书馆的有机坡度。在我的一个大型应用程序中,所有的窗口类都以Win为前缀,所有的信号处理模块都以Mod为前缀等等。这些模块中的任何一个都不太可能被重用,因此将每个组放入一个库中没有实际的好处,但几秒钟后就可以看出项目是如何分解为子项目的。
我也认为这是一种糟糕的做法。为什么?就在一天,我认为名称空间的功能是划分内容,所以我不应该将所有内容都放在一个全局包中而破坏它。
然而,如果我经常使用“cout”和“cin”,我会写:使用std::cout;使用std::cin;在.cpp文件中(当它使用include传播时,不会在头文件中)。我想,没有一个理智的人会说出一条小溪的名字
为了回答你的问题,我实际上是这样看的:很多程序员(不是所有人)都调用命名空间std。因此,人们应该养成习惯,不要使用与命名空间std中的名称冲突或使用相同名称的东西。这是一个很大的事实,但与严格来说可能出现的连贯单词和假名的数量相比,这并不是那么多。
我是说真的。。。说“不要依赖于这个存在”只是让你依赖于它不存在。您经常会遇到借用代码片段并不断修复它们的问题。只需将用户定义的和借用的内容保持在有限的范围内,并且非常节省全局变量(老实说,全局变量几乎永远是“现在编译,以后理智”的最后手段)。我真的认为这是你老师的坏建议,因为使用std对“cout”和“std::cout”都有效,但不使用std只对“std:”cout有效。你不会总是幸运地编写自己的代码。
注意:在真正了解编译器的工作原理之前,不要过于关注效率问题。只要有一点编码经验,在你意识到他们能够将好的代码概括成简单的东西之前,你不必了解他们太多。每一点都很简单,就像你用C语言写了整件事一样。
短版本:不要在头文件中使用全局using声明或指令。可以在实现文件中使用它们。以下是Herb Sutter和Andrei Alexandrescu在C++编码标准中对这个问题的看法(我用粗体强调):
总结命名空间using是为了方便您,而不是为了强加给他人:不要在#include指令之前编写using声明或using指令。推论:在头文件中,不要使用指令或声明编写命名空间级别;相反,显式命名空间限定所有名称。(第二条规则与第一条规则相同,因为标头永远无法知道后面可能出现的其他标头#includes。)讨论简而言之:在#include指令之后,你可以也应该在你的实现文件中自由地使用命名空间使用声明和指令,并对此感到满意。尽管重复了相反的断言,但使用命名空间的声明和指令并不是邪恶的,它们不会破坏命名空间的目的。相反,它们使名称空间可用。
在类的头文件中使用名称空间的问题在于,它迫使任何想要使用您的类(通过包括头文件)的人也“使用”(即查看其他名称空间中的所有内容)。
但是,您可以随意在(私有)*.cpp文件中放入using语句。
请注意,有些人不同意我这样说的“感觉自由”,因为尽管cpp文件中的using语句比头文件中的要好(因为它不会影响包含头文件的人),但他们认为这仍然不好(因为根据代码的不同,这可能会使类的实现更难维护)。这个C++超级FAQ条目说,
using指令存在于遗留的C++代码中,用于简化向命名空间的转换,但您可能不应该定期使用它,至少不应该在新的C++代码。
常见问题解答建议了两种选择:
使用声明:使用std::cout;//using声明允许您无条件使用coutcout<<“值:”;只需键入std::std::cout<<“值:”;