使用std :: <type> vs使用std命名空间

San*_*fer 2 c++ using

使用using声明的两种方法是

using std::string;
using std::vector;
Run Code Online (Sandbox Code Playgroud)

要么

using namespace std;
Run Code Online (Sandbox Code Playgroud)

哪种方式更好?

=========满意答案下面=============

简而言之,在函数内使用声明是无害的,只要给出本地作用域关注,而全局使用声明是危险的,因为它们可能导致命名空间相交,从而使编译器混乱.

通常我们喜欢使用命名空间中的每个名称而没有限定条件.这可以通过为命名空间中的每个名称提供using声明来实现,但这很繁琐,并且每次在命名空间中添加或删除新名称时都需要额外的工作.或者,我们可以使用using-directive来请求命名空间中的每个名称都可以在我们的范围内访问而无需限定.[...] [...]使用using-directive从一个经常使用的知名库中获取名称,这是一种简化代码的流行技术.这是本书中用于访问标准库设施的技术.[...]在一个函数中,using-directive可以安全地用作符号方便,但是应该注意全局使用指令,因为过度使用可能导致命名空间被引入以避免名称冲突.[...]因此,我们必须谨慎使用全球范围内的使用指令.特别是,除非在非常特殊的情况下(例如,为了帮助转换),不要在头文件中的全局范围中放置using-directive,因为你永远不知道标头可能在哪里#included.

感谢Jonathan Wakely的报价.

Jon*_*ely 9

这取决于.

如果要将单个名称注入另一个范围,则using-declaration更好,例如

namespace foolib
{
  // allow vector to be used unqualified within foo,
  // or used as foo::vector
  using std::vector;

  vector<int> vec();

  template<typename T> struct Bar { T t; };

  template<typename T>
  void swap(Bar<T>& lhs, Bar<T>& rhs)
  {
    using std::swap;
    // find swap by ADL, otherwise use std::swap
    swap(lhs.t, rhs.t);
  }
}
Run Code Online (Sandbox Code Playgroud)

但有时你只需要所有的名字,这就是使用指令所做的.这可以在函数中本地使用,也可以在源文件中全局使用.

using namespace只有在你确切知道所包含的内容的情况下才能放在函数体之外,这样才能安全(即不在标题中,你不知道在标题之前或之后会包含什么内容)尽管很多人仍然不赞成这个用法(阅读为什么"使用命名空间std"的答案被认为是不好的做法?详情):

#include <vector>
#include <iostream>
#include "foolib.h"
using namespace foo;  // only AFTER all headers

Bar<int> b;
Run Code Online (Sandbox Code Playgroud)

使用using-directive的一个很好的理由是命名空间只包含少量有意隔离的名称,并且设计为using-directive使用:

#include <string>
// make user-defined literals usable without qualification,
// without bringing in everything else in namespace std.
using namespace std::string_literals;
auto s = "Hello, world!"s;
Run Code Online (Sandbox Code Playgroud)

所以没有一个答案可以说一个普遍优于另一个,它们有不同的用途,每个答案在不同的情况下都更好.

关于第一次使用using namespace,C++的创建者Bjarne Stroustrup在The C++ Programming Language,4th Ed(强调我的)中的§14.2.3中有这个说法:

通常我们喜欢使用命名空间中的每个名称而没有限定条件.这可以通过为using命名空间中的每个名称提供-declaration 来实现,但这很繁琐,并且每次在命名空间中添加或删除新名称时都需要额外的工作.或者,我们可以使用using-directive来请求命名空间中的每个名称都可以在我们的范围内访问而无需限定.[...]
[...]使用using-directive从经常使用的知名库中获取名称,这是一种简化代码的流行技术.这是本书中用于访问标准库设施的技术.[...]
在一个函数中,using-directive可以安全地用作符号方便,但是应该注意全局using-directives,因为过度使用可能导致命名空间被引入以避免命名冲突.[...]
因此,我们必须谨慎对待using全球范围内的指导.特别是,using除非在非常特殊的情况下(例如,为了帮助转换),不要在头文件中的全局范围中放置-directive,因为您永远不知道标头可能在哪里#include.

对我来说,这似乎是更好的建议,而不仅仅是坚持它是坏的,不应该使用.

  • 我相信你知道自己在做什么,并且可能不会做出错误的决定.(尽管ISTR Dave Abrahams讲述了这个曾经让他感觉如何)但是看看C++程序员在这里提出了什么问题.看看那些可怕的C++代码,运行我们文明所依赖的关键基础设施.你真的希望那些C++程序员从你的答案中删除"如果你知道你在做什么就可以了"的建议吗?知道你知之甚少需要很多知识,而IMNSHO很少有C++程序员具备这方面的知识.我宁愿他们安全而不是抱歉. (5认同)
  • 在我必须处理的代码的重要特征列表中,我将"符号方便"waaayyy排在"可证明的正确性"之下.明确地编写命名空间将客观地使编码器的代码更清晰_和_读取它的人."符号方便"是对这一重要目标造成伤害的一个非常糟糕的借口.我也有时使用_using declaration_或(gasp!)甚至_using directives_ - 但是很少且非常严格地从不在函数范围之外.世界上没有任何便利可以超过其他一切会造成损害的安全. (4认同)
  • 如果这个POV让我不同意Bjarne,那就这样吧.IME他非常优雅地对待不同意见.另外,我之前说过,我认为非常不幸的是我知道的每一本C++书都会跳过`std ::`前缀.这通常是出于布局原因而完成的,但几乎和往常一样,因为作者在引入命名空间之前很久就已经存在并且从来没有喜欢它们.我在90年代初期学习了C++,多年后,当命名空间出现时,我认为它们是天赐的,因为它们解决了我遇到过的非常现实的问题. (4认同)
  • @JonathanWakely vOv我猜那是关于它的.我得到你来自哪里,货物崇拜规则不是一个好主意.我只看到风险远大于奖励. (3认同)
  • 恕我直言,只有最后一点才有意义(像`string_literals`或`placeholders`这样的专用命名空间),但我仍然倾向于制作更短的命名空间别名.*你确切地知道所包含的是什么,所以它是安全的*它是危险的,并且已在[这个答案]中提到(http://stackoverflow.com/a/1452738/752976). (2认同)
  • **主持人注**:评论并非旨在进行广泛的讨论,我们为此提供了聊天室。我不介意将此残骸转换为聊天室。 (2认同)