【问题标题】:Using Namespace std使用命名空间标准
【发布时间】:2011-08-29 23:19:54
【问题描述】:

我在学校上编程课,我想在课外开始做一些 c++ 编程。我的学校使用 Microsoft Visual C++ 6.0(从 1998 年开始),所以它仍然使用 <iostream.h> 而不是 <iostream>using namespace std。当我开始工作时,我不知道如何以及何时使用using namespace std,何时只使用std::cout<<"Hello World!"<<'\n';(例如)之类的东西,以及命名空间关键字的限制和其他用途。特别是,如果我想用 iostream 和 iomanip 制作一个程序,我是否必须两次声明“使用命名空间 std”,或者是否有不同的东西我也必须使用,或者我可以做同样的事情吗?我用 iostream 做了什么?我试着用谷歌搜索它,但我真的什么都不懂。提前感谢您的帮助。

【问题讨论】:

    标签: c++ visual-c++ header namespaces std


    【解决方案1】:

    如果您使用不带.h 的标头名称,则其中声明/定义的内容将位于std 命名空间中。您只需在要导入内容的范围内使用一次using namespace std; 即可获得所有内容;多个using namespace std; 无济于事。

    不过,我一般建议不要使用using namespace std;。例如,我更喜欢说using std::cout;,以防止std 中的名称与我的冲突。

    例如:

    #include <iostream>
    #include <iomanip>    
    
    int main()
    {
         using namespace std;
    
         int left = 1, right = 2;
         cout << left << " to " << right << "\n";
    }
    

    可能会引起神秘的问题,因为leftright 存在于std 命名空间中(作为IO 操纵器),如果你懒惰地说using namespace std;,它们就会被导入。如果您打算实际使用 IO 操纵器而不是输出变量,您可能会有点失望。但无论哪种方式,意图都不明显。也许你只是忘记了你有名为leftright 的整数。

    相反,如果你说

    #include <iostream>
    #include <iomanip>
    
    int main()
    {
        using std::cout;
    
        int left = 1, right = 2;
        cout << left << " to " << right << "\n";
    }
    

    #include <iostream>
    #include <iomanip>
    
    int main()
    {
         int left = 1, right = 2;
         std::cout << left << " to " << right << "\n";
    }
    

    一切都按预期进行。此外,您还可以查看您实际使用的内容(在这种情况下,不包括来自 &lt;iomanip&gt; 的任何内容),因此更容易将您的包含内容精简到您需要的内容。

    【讨论】:

    • 如果你要告诉某人不要使用using namespace std,那么至少给他一个例子说明为什么他不应该这样做。很明显,他对命名空间比较陌生,所以像这样给他盲目的包罗万象的建议弊大于利。
    • 是吗?它不会伤害任何东西,而且它往往会导致更精确的意图陈述。我会说最好给新手一般指导方针(不是“盲目的无所不包的建议”,考虑到我确实给出了一个理由——实际上是两个——并且说“一般”而不是“总是”)而不是总是尝试向那些还没有真正“理解”这个概念的人解释为什么。直到它点击,解释只是噪音。一旦点击,原因就很明显了。
    • @cHao,解释会神奇地出现在他们的脑海里吗?
    • @cHao。很多。我只是说直到我上大学一半才真正理解using namespace std,坦率地说,它并没有影响到我。如果有人在高中时告诉我,“不要使用它!!1!!”,这不会对我作为程序员的技能产生任何影响。但是,如果有人解释它,它可能有机会坚持下去。盲目的建议会造就盲目的程序员。有意义的建议使程序员成为聪明的程序员。
    • @Stargazer:“有意义的”建议在很大程度上取决于被建议者理解含义的能力。直到他们这样做,我听起来像查理布朗的老师。我有太多次向某人详细解释事情,然后他们就像“等等,什么?”因为基本面不存在。所以我发现新手最好(对他们来说,为了我的理智,为了世界)粗略地梳理它,让他们在详细说明之前问为什么。如果他们不知道为什么最终,IMO 他们永远不会成为“聪明的程序员”——而愚蠢的程序员可能会因为细节而变得危险。
    【解决方案2】:

    Here 是一个很好的链接,它描述了命名空间及其工作方式。

    这两种方法都是正确的,也就是说,您可以使用“using”语句引入命名空间,也可以限定命名空间的所有成员。这是编码风格的问题。我更喜欢使用命名空间进行限定,因为它让读者清楚地知道函数/类是在哪个命名空间中定义的。

    此外,如果您包含多个文件,则不必两次引入命名空间。一个 using 语句就足够了。

    【讨论】:

      【解决方案3】:

      特定于using namespace std

      你真的不应该在头文件中使用它。通过这样做,您已将整个 'std' 导入到全局命名空间中,供包含您的头文件的任何人或包含您的文件的文件的任何其他人使用。

      在 .cpp 文件中使用它,这是个人喜好。我通常不会将整个 std 导入到全局命名空间中,但自己这样做似乎没有任何害处,以节省一些输入。

      【讨论】:

        【解决方案4】:

        好的,有一些东西,但它是可以管理的。

        首先,两者的区别:

        using namespace std;
        ...
        cout << "Something" << endl;
        

        并使用

        std::cout << "Something" << std::endl;
        

        只是范围问题。范围只是说明编译器如何识别变量和函数名称等的一种奇特方式。命名空间只不过是在该命名空间内的所有变量上添加了一层额外的范围。当您键入 using namespace std 时,您会将命名空间 std 中的所有内容都移到全局范围内,这样您就可以使用较短的 cout 而不是更完整的 std::cout

        要了解命名空间的一件事是它们跨越文件。 &lt;iostream&gt;&lt;iomanip&gt; 都使用命名空间 std。因此,如果你同时包含两者,那么 using namespace std 的声明将对这两个文件都进行操作,并且两个文件中的所有符号都将移动到程序的全局范围(或​​函数的范围,如果你在函数中使用它) .

        会有人告诉你“不要使用using namespace std!!!!”,但他们很少告诉你原因。假设我有以下程序,我要做的就是定义两个整数并将它们打印出来:

        #include <iostream>
        
        using namespace std;
        
        int main(int argc, char** argv) {
            int cout = 0;
            int endl = 1;
            cout << cout << endl << endl;     // The compiler WILL freak out at this :)
            return 0;
        }
        

        当我使用using namespace std 时,我为命名冲突打开了大门。如果我(随机)将一个变量命名为与头文件中定义的相同,那么您的程序将中断,您将很难找出原因。

        不使用using namespace std语句,我可以编写与以前相同的程序(但让它工作):

        #include <iostream>
        
        int main(int argc, char** argv) {
            int cout = 0;
            int endl = 1;
            std::cout << cout << endl << std::endl; // Compiler is happy, so I'm happy :)
            return 0;
        }
        

        希望这已经澄清了一些事情。

        【讨论】:

        • 谢谢,这个解释帮助很大。主要是因为它使用我理解的代码。我之前读到的很多东西都有头文件和其他我以前从未听说过的东西(考虑到我使用 c++ 不到六个月的事实,这并没有说太多)。现在你为我简化了这个,我应该能够更轻松有效地编写代码。
        • 我看不出你提到的那一行“编译器会发疯”的原因。 coutendl 局部变量会影响 std:: 版本,0 &lt;&lt; 0 &lt;&lt; 1 &lt;&lt; 1 完全有效。
        • @jamesdlin,warning C4552: '&lt;&lt;' : operator has no effect; expected operator with side-effect。我可以挑剔,但通常会导致人们完全忽略这一点。
        【解决方案5】:

        问得好,瑞恩。 using namespace 所做的是将给定命名空间(作用域)中的所有符号导入到使用它的作用域中。例如,您可以执行以下操作:

        namespace A {
          struct foo {};
        }
        
        namespace B {
          using namespace A;
        
          struct bar : foo {};
        }
        

        在上述示例中,命名空间 A 中的所有符号都在命名空间 B 中可见,就像它们在那里声明一样。

        此导入仅对给定的翻译单元产生影响。因此,例如,当在您的实现文件(即.cpp)中执行using namespace std; 时,您基本上将所有符号从std 命名空间导入到全局范围内。

        您还可以导入某些符号而不是所有符号,例如:

        using std::cout;
        using std::endl;
        

        您可以在全局范围、命名空间范围或函数范围内执行此操作,如下所示:

        int main ()
        {
           using namespace std;
        }
        

        由程序员决定何时使用完全限定名称以及何时使用using 关键字。通常,将using 放入头文件是一种非常糟糕的做法。专业的 C++ 程序员几乎从不这样做,除非这是解决某些问题所必需的,或者他们 100% 确定它不会为使用该标头的人弄乱类型解析。

        但是,在源文件中(没有人包含源文件),只要在不同的命名空间中没有冲突的名称,就可以执行任何类型的 using 语句。这只是口味问题。例如,如果在整个代码中使用了大量来自不同名称空间的符号,我希望至少有一些关于它们实际声明位置的提示。但是每个人都熟悉 STL,所以using namespace std; 应该永远不会造成任何伤害。

        也可能有一些长命名空间,在这些情况下命名空间别名会派上用场。例如,有一个 Boost.Filesystem 库,它将其所有符号都放在 boost::filesystem 命名空间中。使用那个命名空间太多了,所以人们通常会这样做:

        namespace fs = boost::filesystem;
        
        fs::foo ();
        fs::bar ();
        

        此外,在标头中使用命名空间别名几乎是可以的,如下所示:

        namespace MyLib {
          namespace fs = boost::filesystem;
        }
        

        .. 并受益于更少的打字。发生的情况是,将使用此标头的用户不会通过说 using namespace MyLib; 来导入整个文件系统库。但是,他们将从您的库中导入可能与其他内容冲突的“fs”命名空间。所以最好不要做,但如果你太想要了,总比在那里说using namespace boost::filesystem好。

        所以回到你的问题。如果您使用 C++ I/O 流编写库,最好不要在标题中包含任何 using 语句,我会在每个 cpp 文件中使用 using namespace std;。例如:

        somefile.hpp:

        namespace mylib {
        
        class myfile : public std::fstream {
        public: 
          myfile (const char *path);
        
         // ...
        };
        
        }
        

        somefile.cpp:

        #include "somefile.hpp"
        
        using namespace std;
        using namespace mylib;
        
        myfile::myfile (const char *path) : fstream (path)
        {
          // ...
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-26
          • 1970-01-01
          • 2013-02-08
          • 1970-01-01
          • 2013-01-12
          相关资源
          最近更新 更多