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


当前回答

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

命名空间std包含C++标准函数和变量。当您经常使用C++标准函数时,这个名称空间非常有用。

如本页所述:使用命名空间std的语句通常被认为是错误的实践此语句的替代方法是指定使用作用域运算符(::)将标识符所属的命名空间每次我们声明一个类型。请参阅以下意见:在源文件中使用“using namespace std”没有问题当您大量使用命名空间并确信任何东西都不会碰撞。

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

如本页所述:尽管该语句使我们不必在任何时候输入std::我们希望访问std命名空间中定义的类或类型将整个std命名空间导入当前命名空间该计划的一部分。让我们举几个例子来理解为什么可能不是什么好事...现在,在开发的后期阶段,我们希望使用cout是在某个名为“foo”的库中自定义实现的(用于示例)...注意这里有一个歧义,cout指向哪个库?编译器可能会检测到这一点,而不会编译程序。在最坏的情况下在这种情况下,程序仍可能编译,但调用了错误的函数,因为我们从未指定标识符属于哪个命名空间。

其他回答

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

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
    // ...
}

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

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,每个库都有自己的名称空间:

namespace foo {
    void a(float) { /* Does something */ }
}

namespace bar {
    ...
}

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

using namespace foo;
using namespace bar;

void main() {
    a(42);
}

现在一切都很好。当你运行程序时,它会“做一些事情”。但后来你更新了这个栏,让我们假设它变成了这样:

namespace bar {
    void a(float) { /* Does something completely different */ }
}

此时将出现编译器错误:

using namespace foo;
using namespace bar;

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

因此,您需要进行一些维护,以澄清“a”是指foo::a。这是不可取的,但幸运的是它非常容易(只需在编译器标记为不明确的所有调用前面添加foo::)。

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

namespace bar {
    void a(int) { /* Does something completely different */ }
}

此时,您对a(42)的调用突然绑定到bar::a而不是foo::a,并且它不做“某事”,而是做“完全不同的事情”。没有编译器警告或任何内容。你的程序只是默默地开始做一些与以前完全不同的事情。

当你使用一个名称空间时,你会面临这样的风险,这就是为什么人们不喜欢使用名称空间的原因。名称空间中的东西越多,冲突的风险就越大,因此与其他名称空间相比,人们可能更不喜欢使用名称空间std(由于该名称空间中有很多东西)。

最终,这是可写性与可靠性/可维护性之间的权衡。可读性也可能是其中的一个因素,但无论哪种方式,我都能看到这样做的理由。通常,我会说可靠性和可维护性更重要,但在这种情况下,您将不断为相当罕见的可靠性/可维护性影响支付可写性成本。“最佳”权衡将决定您的项目和优先级。

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

经验丰富的程序员也尽量避免在源文件中使用完全限定的名称。这样做的一个次要原因是,除非有充分的理由,否则在代码较少的情况下编写更多的代码是不优雅的。一个主要原因是关闭参数依赖查找(ADL)。

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

因此,以下内容是可以的:

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

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

例如,如果我键入,使用名称空间std;并使用命名空间otherlib;如果只键入cout(恰好两者都有),而不是std::cout(或'otherlib::cout'),则可能会使用错误的一个,并出现错误。使用std::cout更有效。

我最近遇到了关于VisualStudio2010的投诉。事实证明,几乎所有的源文件都有这两行:

using namespace std;
using namespace boost;

许多Boost功能将进入C++0x标准,而Visual Studio 2010有许多C++0x功能,因此这些程序突然无法编译。

因此,避免使用名称空间X;是一种未来校对的形式,一种确保对正在使用的库和/或头文件的更改不会破坏程序的方法。