Possible Duplicate:
Using std Namespace
Why is 'using namespace std;' considered a bad practice in C++?
号
假设我在C++中使用EDCOX1,0,我正在编写一个打印语句。我可以选择:
1 2 3
| using namespace std;
[...]
cout <<"Hello" << endl; |
或
1 2 3 4
| using std::cout;
using std::endl;
[...]
cout <<"Hello" << endl; |
号
或
1
| std::cout <<"Hello" << std::endl; |
我相信,也许这是不正确的,第一个应该避免,因为它会给你的程序增加很多不必要的膨胀。但是,我不知道第二种和第三种风格在性能上是否有任何区别。我看到的大多数使用库的代码都倾向于使用第三种样式;但是对于我来说,如果在使用第二种样式时没有权衡的话,它似乎是最干净、最可读的方法,特别是当您对有问题的函数或对象进行了大量调用时。
有人能启发我吗?
- using namespace xxx;永远不会引入"bloat"(该死的过度使用的词)。问题在于可能存在歧义。"就性能而言——呃……using指令/声明只会更改命名方式,不会更改任何运行时行为(除了调用错误的函数,请参见上文)。
- 我更喜欢第三种风格,因为它总是明确特定的方法/类型/任何东西的来源。我个人还是喜欢它,尽管它引入了更长的"表达"。
- 只多了五封信。键入它,感谢上帝,你不是在写Java。
- 当名称空间前缀变得非常长时,您可以使用第四种选择:名称空间别名。例如,我经常使用namespace mpl = boost::mpl(我确信在我的项目中没有其他名称空间命名为mpl)。
无论您选择哪种方式,都没有性能差异或"膨胀"。
但是,如果你这样做,例如
1 2
| using namespace std;
using namespace boost; |
两个名称空间中的名称冲突会给您带来很多麻烦。
我认为版本3,在任何地方使用std::cout等,更容易阅读,并且可以避免将来的名称冲突。
如果这不是您想要的,选项2是第二好的,因为它只从名称空间中引入了一些选择名称。注意,尽管在您的示例中,由于using声明包含的字符比您在代码的其余部分中不键入std::所节省的字符多,因此在键入时会出现净损失。
- 不同意在代码中填充"std::"是"更容易阅读"…
- @不关心:阅读我在对这个问题的评论中链接的问题。你肯定会同意,输入std::而不必担心名称冲突,这不是一个很坏的权衡。
- 不,有些人不同意。但是,我认为它更容易阅读(一旦你习惯了它),因为你不必想知道名字是从哪里来的。你不必在每一条线上输入std::,是吗?
- @当然可以,但只有在发生碰撞时。
- @Xeo:他没有说这是一个好的还是坏的权衡,只是说他们没有发现方法3的好点。我同意这一点,但我明白为什么其他人(如博)不同意。
- "非芯片"-我们已经看到,当新的C++ 11添加到命名空间STD与来自第三方库的名称发生冲突时,人们会遇到问题。即使你现在没有碰撞,你可能会晚一点!
- @非芯片:我用boost.mpl和boost.fusion做了很多元编程;如果我在某些代码中看到vector,我不知道它是std::vector,boost::mpl::vector还是boost::fusion::vector。有了前缀,没问题。
我的经验法则是:永远不要把using namespace放在a.h中,而是可以在.cpp文件中随意使用。尤其是当它是using namespace std!
- 我同意。您不应该将using语句放在头文件中,因为您将它们强制放入包含它们的任何其他文件中。这很可能是OP在他检查的其他文件中没有看到它们的原因:如果它们属于第三方库,那么它们很可能是头文件。至于.cpp文件,只要避免名称冲突,就要力求清晰。任何人都不太可能重用来自std名称空间的名称,所以我再次同意。
- @Gorpik"任何人都不太可能重复使用来自std的名字",你应该看看到底有多少这样的问题归结为重新使用std的名字和发生冲突。为了避免重复使用它们,首先需要知道它们是名称空间的一部分。我绝不会在任何地方使用using namespace std。
- @戈尔皮克这是一个伟大的评论!我要强调一下,因为@andera bergia在他的回答中没有真正提到:头文件中的任何using语句都是错误的。不仅仅是using namespace。
- @Juanchopanza:我在考虑商业图书馆作家,但你可能对其他人的代码很正确。
- 坦率地说,从EDCOX1的1个名称空间重用标识符的人不是一个称职的C++程序员。标准库是语言的一部分。
- @Andreabergia:不幸的是,不称职的程序员是现实,我们必须准备好应对他们。
- 请注意,如果项目有自己的名称空间,则可以通过在名称前显式键入std::或your_namespace::来解决由using namespace std引起的不明确名称。
- 不幸的是,我们生活在一个远离理想的世界,在这个世界中,不称职或缺乏经验的程序员(其中许多人有一天会变得称职)必须与更称职的程序员一起工作,他们发现调试这些类型的名称会产生相当繁琐的冲突。
- @安德烈:对不起,这是B。为什么我应该被禁止使用EDCOX1,10,EDCOX1,11,EDCOX1,12,或者我不能想象的东西,因为它是C++ 1x的一部分?Boost现在应该因为像std::shared_ptr和boost::shared_ptr这样的名字冲突而贬低他一半的图书馆吗?名称空间的重点是实现名称重用,这样我们就可以消除命名约定,如mysql_connect()或andreabergia_link_open()…使用干净的名字是能力,使用通用的名字是能力。禁止名称重用是无知的,因为名称集将永远进化。
每种方法产生的代码应该完全相同。从一开始就不会有任何膨胀,因为它只会在编译时将来自std的所有名称提供给代码——不使用的内容不会被占用。实际使用的std中只有cout和endl两个名称,因此编译代码的最终结果是相同的。
优点和缺点是:
在大多数行中,这一行将有更简洁的代码。读过这本书的人可能不得不更仔细地考虑一下cout和endl的定义,尽管这并不是他们所熟知的问题。编译可能需要更长的时间,因为每个名称的可能含义范围都稍大一些,但这可能忽略不计,除非程序很大,并且您正在编译的机器非常弱。如果作用域中的其他命名空间定义了cout或endl,那么名称将不明确,您将被迫使用其他名称之一。
数字1的优点,只引入两个名字就减少了缺点。
与第一个相反。无论是编译器还是开发人员,在查看源代码时都没有含糊不清的地方,但代价是要更加详细。
因此,如果这是整个文件中std的唯一用途,那么使用方法3可能是值得的;如果std中有很多重复使用的东西,那么使用方法1(8)和endl可能是第一;如果大量使用cout和endl,那么使用方法2可能是值得的,但std中没有其他方法。
或者你可以一直使用数字1,除非被一个歧义所强迫去做其他的事情。
这两者并非互相排斥。一个人可以做到:
1 2 3
| using namespace std;
/*...*/
std::cout <<"Hello" << std::endl; |
当然,在这里,std::是多余的,但是我们可以这样做,如果上下文中这些内容不明确,但是std的其他用法不明确,或者人们可能不熟悉某个特定的名称,因此冗余代码有助于可读性。还有一些名称,由于它们的全名是这样的,所以更常见的是,这样做本身就有助于提高可读性。
尽管如此,除非有歧义(无法编译),否则所有这些都会在编译时生成相同的程序。
编辑:
我假设这里有一个.cpp文件,但我同意其他人关于头的看法。在一个.h文件中,您强制对它所包含的所有文件做出决定,并且只需要一个文件具有模糊性,就可以将其作为一个错误的调用。对于开发人员来说,它也不太明显,因为包含位置不靠近使用位置。
如果您真的想在.h文件中使用1或2,那么通过将其放在名称空间、类或函数中来确定using的范围,这样在等待包含该文件的人时就不会有任何意外了。
- +1对于一个非常完整的答案,尽管我理解为什么其他人不同意你的方法1。
- @戈尔皮克用什么方式?(尽管在我看到其他人提到它之前,我甚至没有考虑是否有人会在头文件中这样做,如果这就是你的意思的话)。
- 不,我的意思是有些人完全反对方法1,即使对于.cpp文件也是如此。
- @戈壁啊,够公平的了。他们不能说它没有简明扼要的优势,因为很明显,他们只是认为它不值得,这与我所说的不矛盾。我更担心的是我完全错过了什么。
我通常更喜欢第三种样式,但有时它更紧凑,使用第一或第二种样式更简单。我有时在本地使用。例如:
1 2 3 4 5
| void foo()
{
using namespace std;
//do stuff
} |
但我宁愿不在模块中全局写入using namespace std。