关于C++:为什么”使用命名空间STD”被认为是不好的实践?

Why is “using namespace std” considered bad practice?

别人告诉我,用代码编写using namespace std是错误的,我应该直接使用std::coutstd::cin

为什么using namespace std被认为是一种不好的做法?它是否效率低下,或者是否存在声明不明确变量(与std命名空间中的函数同名的变量)的风险?它会影响性能吗?


这与表演一点关系都没有。但是考虑一下:您使用的是两个名为foo和bar的库:

1
2
using namespace foo;
using namespace bar;

一切正常,你可以从FOO打电话给Blah(),从酒吧打电话给Quux(),没有问题。但是有一天你升级到了新版本的foo 2.0,它现在提供了一个名为Quux()的函数。现在您遇到了一个冲突:foo 2.0和bar都将Quux()导入到全局命名空间中。这需要花费一些精力来修复,特别是当函数参数恰好匹配时。

如果你使用了foo::Blah()bar::Quux(),那么引入foo::Quux()就不是什么大事了。


我同意格雷格写的所有东西,但我想补充一句:它甚至可能比格雷格说的更糟!

库foo 2.0可以引入一个函数,Quux(),对于您对Quux()的一些调用来说,这个函数显然比您多年来调用的bar::Quux()代码更匹配。然后你的代码仍然在编译,但是它会悄悄地调用错误的函数,上帝知道什么。这是最坏的情况。

记住,std名称空间有大量的标识符,其中许多标识符是非常常见的(如listsortstringiterator等),它们也很可能出现在其他代码中。

如果您认为这不太可能:在给出这个答案半年后,这里有一个关于堆栈溢出的问题,在哪里发生了几乎完全正确的事情(由于省略了std::前缀而调用了错误的函数)。这是另一个更近的例子。所以这是一个真正的问题。

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

在十年的时间里,这个项目增加到了几百万行代码。由于这些讨论反复出现,我曾经好奇(允许的)功能范围using在项目中实际使用的频率。我找到了它的来源,只找到了一两打使用它的地方。对我来说,这表明,一旦尝试过,开发人员发现std::不够痛苦,即使每100 kloc使用一次指令,即使在允许使用的地方。

最重要的是:明确地预加前缀不会造成任何伤害,很少需要习惯,并且有客观的优势。特别是,它使代码更容易被编译器和人类读者解释——这可能是编写代码时的主要目标。


using namespace放入类的头文件中的问题是,它强制任何想要使用类(通过包括头文件)的人也"使用"(即查看所有内容)那些其他名称空间。

但是,您可以在(private).cpp文件中随意放置using语句。

注意,有些人不同意我这样说的"感觉自由"——因为尽管cpp文件中的using语句比头文件中的语句更好(因为它不会影响包含头文件的人),但他们认为它仍然不好(因为根据代码的不同,它可能会使类的实现更难维护)。.本常见问题解答主题说明:

The using-directive exists for legacy C++ code and to ease the transition to namespaces, but you probably shouldn’t use it on a regular basis, at least not in your new C++ code.

常见问题解答提出了两种备选方案:

  • 使用声明:

    1
    2
    using std::cout; // a using-declaration lets you use cout without qualification
    cout <<"Values:";
  • 只需输入标准:

    1
    std::cout <<"Values:";


我最近遇到一个有关Visual Studio 2010的投诉。结果发现几乎所有的源文件都有这两行:

1
2
using namespace std;
using namespace boost;

C++0x标准中有很多Boost特性,VisualNasnStudio & Nbsp 2010有很多C++ 0x特性,所以这些程序突然没有编译。

因此,避免using namespace X;是一种未来的校对方式,确保对正在使用的库和/或头文件进行更改不会破坏程序。


短版本:不要在头文件中使用全局声明或指令。在实现文件中随意使用它们。下面是萨特和Andrei Alexandrescu关于C++编码标准中的这个问题(强调强调我的):

Summary

Namespace usings are for your convenience, not for you to inflict on others: Never write a using declaration or a using directive before an #include directive.

Corollary: In header files, don’t write namespace-level using directives or using declarations; instead, explicitly namespace-qualify all names. (The second rule follows from the first, because headers can never know what other header #includes might appear after them.)

Discussion

In short: You can and should use namespace using declarations and directives liberally in your implementation files after #include directives and feel good about it. Despite repeated assertions to the contrary, namespace using declarations and directives are not evil and they do not defeat the purpose of namespaces. Rather, they are what make namespaces usable.


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

1
2
3
4
5
6
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::sinstd::cos…)因为它较短,并且能够处理用户定义的浮点类型(通过依赖于参数的查找)。


不要在全球范围内使用它

只有在全球使用时才被认为是"坏"的。因为:

  • 您使正在编程的名称空间混乱。
  • 当您使用多个using namespace xyz时,读者将很难看到特定标识符来自何处。
  • 对于您的源代码的其他读者来说,无论什么是正确的,对于最经常阅读它的人来说,都是正确的:您自己。一两年后再来看看……
  • 如果你只谈论EDCOX1,1,你可能不知道你抓取的所有东西,当你添加另一个EDCOX1,2,或者移动到一个新的C++版本,你可能会得到你不知道的名字冲突。

你可以在本地使用

继续在本地(几乎)免费使用它。当然,这会阻止你重复std::,重复也很糟糕。

本地使用的成语

在C++ 03中有一个成语——样板代码——用于为类实现EDCOX1×4函数。有人建议您实际使用本地using namespace std--或至少使用using std::swap

1
2
3
4
5
6
7
8
9
10
11
12
13
class Thing {
    int    value_;
    Child  child_;
public:
    // ...
    friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
    using namespace std;      // make `std::swap` available
    // swap all members
    swap(a.value_, b.value_); // `std::stwap(int, int)`
    swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}

这有以下魔力:

  • 编译器将为value_选择std::swap,即void std::swap(int, int)
  • 如果实现了一个重载void swap(Child&, Child&),编译器将选择它。
  • 如果没有这种重载,编译器将使用void std::swap(Child&,Child&),并尽可能地交换这些重载。

有了C++ 11,就没有理由再使用这个模式了。改变了std::swap的实现,以发现并选择潜在的过载。


如果导入正确的头文件,则在全局范围内突然出现名称,如hexleftpluscount。如果您不知道std::包含这些名称,这可能会令人惊讶。如果您还尝试在本地使用这些名称,可能会导致相当多的混淆。

如果所有标准的东西都在自己的名称空间中,那么就不必担心与代码或其他库的名称冲突。


经验丰富的程序员使用任何能解决他们问题的方法,避免任何能产生新问题的方法,并且出于这个确切的原因,他们避免使用头文件级别的指令。

经验丰富的程序员还试图避免对源文件中的名称进行完全限定。这样做的一个次要原因是,除非有充分的理由,否则在代码足够少的情况下编写更多的代码是不明智的。这主要是因为关闭了依赖于参数的查找(ADL)。

这些好理由是什么?有时程序员明确地想关闭ADL,而有时他们想消除歧义。

所以下面是可以的:

  • 在函数实现中使用指令和声明的函数级
  • 在源文件中使用声明的源文件级别
  • (有时)使用指令的源文件级别

  • 另一个原因是惊喜。

    如果我看到cout << blah,而不是std::cout << blah

    我想这是什么东西?这是正常的cout吗?有什么特别的吗?


    我同意它不应该在全球范围内使用,但是在本地使用并不那么邪恶,就像在namespace中那样。下面是一个"C++编程语言"的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    namespace My_lib {

        using namespace His_lib; // everything from His_lib
        using namespace Her_lib; // everything from Her_lib

        using His_lib::String; // resolve potential clash in favor of His_lib
        using Her_lib::Vector; // resolve potential clash in favor of Her_lib

    }

    在这个例子中,我们解决了可能的名称冲突和由它们的组成引起的歧义。

    其中明确声明的名称(包括使用诸如His_lib::String等声明声明声明的名称)优先于使用指令(using namespace Her_lib在另一个作用域中访问的名称。


    我也认为这是一种不好的做法。为什么?就在一天,我认为名称空间的功能是划分东西,所以我不应该把所有东西都扔到一个全局包中。但是,如果我经常使用"cout"和"cin",我会在cpp文件中写入:using std::cout; using std::cin;(从未在头文件中使用,因为它与#include一起传播)。我认为没有一个理智的人会说出一条河流的名字:coutcin。;)


    很高兴看到代码并知道它的作用。如果我看到std::cout,我知道那是std库的cout流。如果我看到cout,我就不知道了。它可以是std库的cout流。或者在同一个函数中,可能有一个int cout = 0;10行更高。或者该文件中名为coutstatic变量。它可以是任何东西。

    现在以一百万行代码为基础,这并不是特别大,你在搜索一个bug,这意味着你知道在这一百万行中有一行代码不能做它应该做的。cout << 1;可以读取一个名为coutstatic int,将其左移一位,并丢弃结果。找虫子,我得检查一下。你知道我真的很喜欢看std::cout吗?

    如果你是一名教师,而且从不需要为生活而写和维护任何代码,那么这是其中一个看起来非常好的主意。我喜欢在以下地方看到代码:(1)我知道它做什么;(2)我相信编写代码的人知道它做什么。


    一切都是为了管理复杂性。使用名称空间将拉入您不想要的东西,因此可能会使调试更加困难(我说可能)。到处使用std::很难阅读(更多的文本和所有这些)。

    马的课程-管理你的复杂性如何你能最好地和感觉能力。


  • 您需要能够阅读由与您有不同风格和最佳实践意见的人编写的代码。

  • 如果你只使用cout,没人会感到困惑。但是当有很多名称空间在你周围飞来飞去,你看到这个类,你不确定它到底做了什么,让名称空间显式作为一种注释。您可以第一眼看到,‘哦,这是一个文件系统操作’或者‘这是在做网络工作’。


  • 考虑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // myHeader.h
    #include <sstream>
    using namespace std;


    // someoneElses.cpp/h
    #include"myHeader.h"

    class stringstream {  // uh oh
    };

    注意,这是一个简单的例子,如果您有包含20个include和其他导入的文件,那么您将有大量的依赖项来解决这个问题。更糟糕的是,根据冲突的定义,您可以在其他模块中获得不相关的错误。

    这并不可怕,但如果不在头文件或全局命名空间中使用它,就可以省去自己的麻烦。在非常有限的范围内完成这项工作可能没问题,但我从来没有遇到过输入额外的5个字符来说明我的函数来自何处的问题。


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

    所以只要把它们当作保留名称,比如"int"或"class",就可以了。

    人们应该停止对这件事如此无礼。你的老师一直都很好。只需使用一个名称空间;这是首先使用名称空间的全部要点。不能同时使用多个。除非是你自己的。因此,重新定义也不会发生。


    我同意这里的其他观点,但希望解决有关可读性的问题——您可以通过在文件、函数或类声明的顶部使用typedef来避免所有这些问题。

    我通常在类声明中使用它,因为类中的方法倾向于处理类似的数据类型(成员),typedef是分配在类上下文中有意义的名称的机会。这实际上有助于类方法定义的可读性。

    1
    2
    3
    4
    5
    6
    //header
    class File
    {
       typedef std::vector<std::string> Lines;
       Lines ReadLines();
    }

    在实施过程中:

    1
    2
    3
    4
    5
    6
    7
    //cpp
    Lines File::ReadLines()
    {
        Lines lines;
        //get them...
        return lines;
    }

    与之相反:

    1
    2
    3
    4
    5
    6
    7
    //cpp
    vector<string> File::ReadLines()
    {
        vector<string> lines;
        //get them...
        return lines;
    }

    或:

    1
    2
    3
    4
    5
    6
    7
    //cpp
    std::vector<std::string> File::ReadLines()
    {
        std::vector<std::string> lines;
        //get them...
        return lines;
    }


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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
        / / ...
    }

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

    1
    2
    3
    4
    5
    6
    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


    澄清问题的具体例子。假设您有两个库,foo和bar,每个库都有自己的名称空间:

    1
    2
    3
    4
    5
    6
    7
    namespace foo {
        void a(float) { /* does something */ }
    }

    namespace bar {
        ...
    }

    现在假设您在自己的程序中同时使用foo和bar,如下所示:

    1
    2
    3
    4
    5
    6
    using namespace foo;
    using namespace bar;

    void main() {
        a(42);
    }

    在这一点上,一切都很好。当你运行你的程序时,它会"做一些事情"。但后来你更新了这个工具栏,让我们假设它已经改变为:

    1
    2
    3
    namespace bar {
        void a(float) { /* does something completely different */ }
    }

    此时,您将得到一个编译器错误:

    1
    2
    3
    4
    5
    6
    using namespace foo;
    using namespace bar;

    void main() {
        a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
    }

    因此,您需要做一些维护,以澄清您所指的"a"(即foo::a)。这可能是不可取的,但幸运的是,它相当容易(只需在对a的所有调用之前添加foo::,编译器就会将其标记为不明确)。

    但是想象一下另一种情况,酒吧变成了这样:

    1
    2
    3
    namespace bar {
        void a(int) { /* does something completely different */ }
    }

    此时,你对a(42)的调用突然绑定到bar::a而不是foo::a,而不是执行"某个操作",而是执行"完全不同的操作"。没有编译器警告或任何内容。你的程序只是静静地开始做一些与以前完全不同的事情。

    当您使用一个名称空间时,您会冒这样的风险,这就是为什么人们不愿意使用名称空间的原因。名称空间中的内容越多,冲突的风险就越大,因此使用名称空间std(由于该名称空间中的内容数量多)的人可能比使用其他名称空间更不舒服。

    最终,这是可写性与可靠性/可维护性之间的权衡。可读性也可以考虑,但我可以看到这两种情况的论据。通常我会说可靠性和可维护性更重要,但在这种情况下,您将经常为相当罕见的可靠性/可维护性影响支付可写性成本。"最佳"权衡将决定你的项目和你的优先顺序。


    使用名称空间std的一个示例由于计数的模糊性而引发编译错误,这也是算法库中的一个函数。

    1
    2
    3
    4
    5
    6
    7
    8
    #include <iostream>

    using namespace std;

    int count = 1;
    int main() {
        cout<<count<<endl;
    }


    我认为在任何情况下都不一定是不好的做法,但使用时要小心。如果您正在编写一个库,那么您可能应该使用带有名称空间的范围解析操作符来防止您的库与其他库发生冲突。对于应用程序级代码,我看不出它有什么问题。


    它不会使您的软件或项目性能变差,在源代码开头包含名称空间也不错。根据您的需求和开发软件或项目的方式,包含using namespace std指令的方式有所不同。

    EDCOX1(1)包含C++标准函数和变量。当您经常使用C++标准函数时,这个命名空间很有用。

    As is mentioned in this page:

    The statement using namespace std is generally considered bad
    practice. The alternative to this statement is to specify the
    namespace to which the identifier belongs using the scope operator(::)
    each time we declare a type.

    And see this opinion:

    There is no problem using"using namespace std" in your source file
    when you make heavy use of the namespace and know for sure that
    nothing will collide.

    有些人曾说,将using namespace std包含在源文件中是一种糟糕的做法,因为您从该名称空间调用了所有函数和变量。当您想要定义一个与namespace std中包含的另一个函数同名的新函数时,您将重载该函数,它可能由于编译或执行而产生问题。它不会像您期望的那样编译或执行。

    As is mentioned in this page:

    Although the statement saves us from typing std:: whenever
    we wish to access a class or type defined in the std namespace, it
    imports the entirety of the std namespace into the current namespace
    of the program. Let us take a few examples to understand why this
    might not be such a good thing

    ...

    Now at a later stage of development, we wish to use another version of
    cout that is custom implemented in some library called"foo" (for
    example)

    ...

    Notice how there is an ambiguity, to which library does cout point to?
    The compiler may detect this and not compile the program. In the worst
    case, the program may still compile but call the wrong function, since
    we never specified to which namespace the identifier belonged.


    "为什么使用命名空间STD?"被认为是C++中的一个坏习惯吗?

    我换一种说法:为什么有些人认为输入5个额外的字符很麻烦?

    例如,编写一个数字软件,当"vector"是问题域最重要的概念之一时,为什么还要考虑通过将一般的"std::vector"缩减为"vector"来污染全局命名空间?


    这取决于它的位置。如果它是一个公共头,那么您将通过将其合并到全局名称空间来减小名称空间的值。记住,这可能是一种使模块全局化的好方法。


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


    我同意其他人的看法——这是在要求名字冲突,模棱两可,然后事实是它不那么明确。虽然我可以看到using的使用,但我个人的偏好是限制它。我也会强烈考虑其他人指出的:好的。

    如果您想找到一个可能是一个相当常见的名称的函数名,但只想在std名称空间中找到它(或者反过来,您想更改不在名称空间std中、名称空间X中的所有调用),那么您打算如何做呢?你可以写一个程序来完成它,但是花时间在你的项目本身上,而不是写一个程序来维护你的项目,难道不是更好吗?好的。

    就我个人而言,我并不介意std::前缀。我更喜欢它的外观而不是没有它。我不知道这是不是因为它是明确的并且对我说"这不是我的代码…我正在使用标准库"或者如果它是其他东西,但我认为它看起来更好。这可能是奇怪的,因为我最近才进入C++(使用和仍然做C和其他语言更长的时间,C是我最喜欢的语言的所有时间,就在大会)。好的。

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

    除此之外,还可以有名称空间别名。下面是一个例子,说明它在哪些地方有用,而这些地方可能没有被提及。我使用C++ 11标准,特别是用LIbSTDC++ ++。嗯,它没有完整的std::regex支持。当然,它会编译,但它会抛出一个异常,这是程序员端的一个错误。但它缺乏实施。我就是这样解决的。安装Boost的Regex,连接它。然后,我执行以下操作,以便当libstdc++完全实现它时,我只需要删除这个块,代码保持不变:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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(但这是一个很好的练习,也是一个让自己成为A、学习另一种语言和B的好方法。尽量不要对对象/类等有太大的偏见,这可能更好地说是不那么封闭、不那么傲慢、更容易接受)。但有用的是一些人已经建议的:我确实使用列表(它是相当通用的,不是吗?)(同样的事情)把两个名字分类,如果我做using namespace std;的话,会引起名字冲突,为此,我更喜欢具体化、控制和知道如果我打算把它作为标准用途,那么我必须指定它。简而言之:不允许假设。好的。

    至于让Boost的regex成为std的一部分。我这样做是为了将来的整合,而且——再次,我完全承认这是一种偏见——我认为这并不像boost::regex:: ...那样丑陋——事实上,这对我来说是另一回事。在C++中有很多东西我还没有完全在外观和方法中接受(另一个例子:可变模板与var ARGs)[虽然我承认可变模板是非常有用的!)即使是我接受的那些人也很困难,我仍然和他们有问题。好的。好啊。


    这是一种不好的做法,通常被称为全球名称空间污染。当多个命名空间具有相同的带签名的函数名时,可能会出现问题,那么编译器将无法确定要调用哪个命名空间,而当您使用类似std::cout的函数调用指定命名空间时,可以避免这一切。希望这有帮助。:)


    根据我的经验,如果您有多个库,比如说,cout,但出于不同的目的,您可能会使用错误的cout

    例如,如果我输入,using namespace std;using namespace otherlib;和type只是不能(恰好两者都有),而不是std::cout'otherlib::cout'的类型,你可能会使用错误的类型,并得到错误,那么使用std::cout更有效。


    为了回答你的问题,我实际上是这样看的:很多程序员(不是所有人)都调用名称空间std。因此,人们应该养成不使用与名称空间std中名称相同的东西的习惯。这是非常理所当然的,但与可能的连贯单词和假名的数量相比,这是不太可能的。这可以严格地说出来。

    我是说真的…说"不要依赖这个存在",就是让你相信它不存在。您经常会遇到借用代码片段并不断修复它们的问题。只要保持你的用户定义和借来的东西在有限的范围内,因为他们应该,并非常节省与全球(老实说,全球应该几乎总是最后的手段,目的是"编译现在,健全以后")。我真的认为这是老师的坏建议,因为使用std对"cout"和"std::cout"都有效,但不使用std只对"std::cout"有效。您并不总是幸运地编写自己的代码。

    注意:在您真正了解编译器的工作原理之前,不要过于关注效率问题。有了一点编码的经验,在你意识到好的代码能够概括为简单的东西之前,你不必对它们了解那么多。每一点都很简单,就好像你用C语言写了整件事一样。好的代码只是它需要的那么复杂而已。


    是的,命名空间很重要。在我的项目中,我需要将一个var声明导入到我的源代码中,但是在编译它时,它与另一个第三方库冲突。

    最后,我不得不用其他方法来绕过它,使代码不那么清晰。


    我认为本地或全局使用应该取决于应用程序。

    因为,当我们在本地使用库时,有时代码会变得一团糟。可读性将下降。

    因此,只有在可能发生冲突的情况下,我们才应该在本地使用库。

    我不是经验丰富的人。所以,如果我错了就告诉我。


    下面是一个示例,说明using namespace std;如何导致名称冲突问题:

    无法在C++中定义全局变量

    在示例中,非常通用的算法名称(std::count名称)与非常合理的变量名称(count名称)冲突。


    老实说,对我来说,这就像讨论缩进的空格数。在头中使用指令会造成损坏。但是在C++文件中呢?如果您同时使用两个名称空间,可能是这样。但如果你使用一个,它更多的是关于风格而不是真正的效率。你知道为什么关于缩进的线程如此流行吗?任何人都可以说点什么,听起来很聪明,很有经验。


    这里有一个观点,我在其他任何答案中都没有找到:只使用一个名称空间。根据大多数答案,名称空间不好的主要原因是,您可能有相互冲突的函数名,这可能导致完全混乱。但是,如果只使用一个名称空间,则不会发生这种情况。决定使用最多的库(可能是using namespace std;)并坚持使用。

    可以认为它有一个不可见的库前缀——std::vector变成了vector。在我看来,这是两个领域中最好的一个:一方面它减少了您必须执行的输入量(如名称空间所预期的那样),另一方面,它仍然要求您使用前缀以提高清晰度和安全性。如果有一个没有名称空间前缀的函数或对象,您知道它来自您声明的名称空间。

    记住,如果你决定在全球范围内使用一个-不要在本地使用其他的。这又回到了另一个答案,即本地名称空间通常比全局名称空间更有用,因为它们提供了各种方便。