简体   繁体   English

为什么我要包含头文件<iostream>使用命名空间 std 后?

[英]why should i include the header file <iostream> after using the namespace std?

Since the namespace std already has the c++ libraries that contain the function definitions(if i am right), then why do we include header files on top of it??.既然命名空间 std 已经有包含函数定义的 C++ 库(如果我是对的),那么我们为什么要在它上面包含头文件??。 Since namespace std includes the c++ standard libraries, I don't see a reason to include the declarations of it separately.由于命名空间 std 包括 c++ 标准库,我认为没有理由单独包括它的声明。

When you do #include <iostream> it causes a set of classes and other things to be included in your source file.当您执行#include <iostream>它会导致一组类和其他内容包含在您的源文件中。 For iostream, and most of the standard library headers, they place these things in a namespace named std .对于 iostream 和大多数标准库头文件,它们将这些东西放在名为std的命名空间中。

So the code for #include <iostream> looks something like this:所以#include <iostream>的代码看起来像这样:

namespace std { 
    class cin  { ... };
    class cout { ... };
    class cerr { ... };
    class clog { ... };
    ...
}

So at this point, you could write a program that looks like:所以此时,你可以编写一个如下所示的程序:

#include <iostream>

int main() {
    std::cout << "hello\n";
    return 0;
}

Now, some people feel that std::cout is too verbose.现在,有些人觉得std::cout太冗长了。 So they do:所以他们这样做:

#include <iostream>
using namespace std;

int main() {
    cout << "hello\n";
    return 0;
}

Personally, I'd recommend against this, and if you really feel that std::cout is too verbose, then I'd suggest that you use a smaller using statement.就个人而言,我不建议这样做,如果您真的觉得std::cout太冗长,那么我建议您使用较小的using语句。

#include <iostream>
using std::cout;

int main() {
    cout << "hello\n";
    return 0;
}

If you're wondering why I would recommend against using namespace std , then I would forward you to the following two other posts on stackoverflow:如果您想知道为什么我不建议using namespace std ,那么我会将您转至以下有关 stackoverflow 的另外两篇文章:

The compiler itself does not have the definitions of the things that are in any namespace (whether it is std or some other namespace).编译器本身没有任何命名空间(无论是std还是其他命名空间)中事物的定义。 That is the role of source files and header files.那就是源文件和头文件的作用。

What using namespace std;什么using namespace std; tells the compiler is that "If you can't find some name in the current namespace, go look in the std namespace as well".告诉编译器是“如果您在当前命名空间中找不到某个名称,也请查看std命名空间”。

What #include <iostream> tells the compiler is that you want the contents of the header called iostream to be included in your sources. #include <iostream>告诉编译器您希望将名为iostream的头文件的内容包含在您的源代码中。 This will provide the compiler with code to do cin , cout and a lot of other related functionality.这将为编译器提供执行cincout和许多其他相关功能的代码。 The content of this file is declared like namespace std { ... all the stuff goes here ... } .这个文件的内容被声明为namespace std { ... all the stuff goes here ... }

The usage of namespace allows someone else, working in namespace math;命名空间的使用允许其他人在namespace math;工作namespace math; to not have to worry about "Hmm, what do I do now, I need a counter for number of entrances, let's call it cin - but hang on, is that ever used anywhere?".不必担心“嗯,我现在该怎么办,我需要一个入口数量的计数器,让我们称之为cin - 但是等等,它在任何地方都使用过吗?”。

This may not be the greatest of examples, but in large projects, it gets increasingly hard to keep track of things and what names they have.这可能不是最好的例子,但在大型项目中,跟踪事物及其名称变得越来越困难。 And C++ is a language intended for large projects of millions of lines of code - and now it starts getting hard to remember if you've used a particular name or not.而 C++ 是一种用于数百万行代码的大型项目的语言 - 现在它开始变得难以记住您是否使用过特定名称。 Namespaces make sure that you don't have to worry about it outside of a particular namespace.命名空间确保您不必在特定命名空间之外担心它。

(Oh, and in my code, I tend to not use using namespace std; , but write std::cout << "Hello, World!" << std::endl; - this helps to make it clear that the cout I'm using here is the std one, and not something else. This is particularly useful when you have several namespaces with similar things, like in my own compiler, where I have my compiler with it's functionality, the std namespace providing some things, and llvm compiler things - if I were to stick using namespace llvm; at the beginning of the code, it would be very hard to track whether Type* p = ... ; is from LLVM or some part of my own code.) (哦,在我的代码中,我倾向于不使用using namespace std; ,而是写std::cout << "Hello, World!" << std::endl; - 这有助于说明cout我'我在这里使用的是std ,而不是其他东西。当您有多个具有相似内容的命名空间时,这特别有用,例如在我自己的编译器中,我的编译器具有它的功能, std命名空间提供了一些东西,以及llvm编译器的事情 - 如果我坚持using namespace llvm;在代码的开头,很难跟踪Type* p = ... ; 是来自 LLVM 还是我自己代码的某些部分。)

...why do we include header files on top of it??? ...为什么我们在它上面包含头文件???

Yes, there is some big confusion here.是的,这里有一些很大的混乱。

Namespaces命名空间

Namespaces are a method to categorize or group together, symbols such as function names.命名空间是一种对函数名称等符号进行分类或分组的方法。

Namespaces are design to prevent name conflicts between different software components, such as libraries.命名空间旨在防止不同软件组件(例如库)之间的名称冲突。

Functions that are a part of the standard language, are grouped under the namespace std .作为标准语言一部分的函数被分组在命名空间std

The C++ language provides statements to reduce the amount of typing when using namespaces. C++ 语言提供了在使用命名空间时减少输入量的语句。 One of these is the using statement.其中之一是using语句。

Header (include) Files头(包括)文件

When you write a program, the compiler is not required to automatically include all the symbol definitions, such a function declarations.编写程序时,编译器不需要自动包含所有符号定义,例如函数声明。 You need to tell it which functions you plan on using.您需要告诉它您计划使用哪些功能。

For example, I could write a program without using the sort or advance functions from the algorithm group.例如,我可以在不使用algorithm组中的sortadvance函数的情况下编写程序。 Therefore I would not include the header file algorithm .因此我不会包括头文件algorithm

The C++ language is designed to be "use what you need", in other words, we can create small programs by only including the functions we need. C++语言被设计成“用你所需要的”,换句话说,我们可以通过只包含我们需要的函数来创建小程序。

Other Platforms其他平台

By the way, there are many other platforms out there than the one you are using.顺便说一句,除了您正在使用的平台之外,还有许多其他平台。

Some platforms need to fit in small memory areas and may not have a keyboard or display (such as embedded controllers).某些平台需要适合小内存区域,并且可能没有键盘或显示器(例如嵌入式控制器)。

So remember, C++ was defined to support platforms from the small and constrained to the large and virtually unconstrained system.所以请记住,C++ 被定义为支持从小型受限系统到大型且几乎不受约束的系统的平台。

Thus the requirement to "include only what you need" theme.因此,要求“仅包含您需要的内容”主题。

Summary概括

In summary, since the C++ languages doesn't automatically, magically, provide the definitions of the entire library, including the template library, you need to tell the compiler which groups of functions you want to use.总之,由于 C++ 语言不会自动、神奇地提供整个库的定义,包括模板库,您需要告诉编译器您要使用哪些函数组。 This allows for quicker compilations since only the required header files are specified.这允许更快的编译,因为只指定了所需的头文件。

Note : Some shops and library supplies like to use the Monolith include system.注意:一些商店和图书馆用品喜欢使用Monolith包含系统。 This means that they have one include file that includes their entire library, whether you use one function or many.这意味着他们有一个包含整个库的包含文件,无论您使用一个函数还是多个函数。 The windows.h is a classic example. windows.h就是一个经典的例子。 One detriment is that when one header file is changed, everything needs to be rebuilt.一个不利因素是,当一个头文件被更改时,所有内容都需要重新构建。 With separated include files, only the components that include the changed header file need to be rebuilt.使用分离的包含文件,只需要重新构建包含更改的头文件的组件。

Use of preprocessor directive #include is as old as c++ itself.预处理器指令 #include 的使用与 C++ 本身一样古老。 And its not going away any sooner.In C++ namespace Doesn't import anything into your program, it just defines the scope of your particular header file's function.So, both are required.它不会很快消失。在 C++ 命名空间中,不会将任何内容导入您的程序,它只是定义了特定头文件功能的范围。因此,两者都是必需的。 Click here to understand why use namespace.单击此处了解为什么要使用命名空间。

Your question is: namespace std has all the definitions of functions/classes of iostream library.您的问题是: namespace std具有iostream库的函数/类的所有定义。 So simply using using namespace std is enough to call or use cout or all other functionalities of iostream library.因此,简单地使用using namespace std就足以调用或使用coutiostream库的所有其他功能。 Why do we have to use line #include <iostream> ?为什么我们必须使用行#include <iostream> It seems redundant.似乎是多余的。

Roughly we can think that iostream library has two files: header and implementation/source file.粗略地我们可以认为iostream库有两个文件:头文件和实现/源文件。 These two files have a namespace called std .这两个文件有一个名为std的命名空间。 The header file only contains the declarations or forward declarations of classes or functions or variables that iostream library is going to use and these declarations or forward declarations are under the std namespace.头文件仅包含iostream库将要使用的类或函数或变量的声明或前向声明,并且这些声明或前向声明位于std命名空间下。 The implementation file contains the actual implementations of the classes or functions or variables and these implementations are under the std namespace;实现文件包含类或函数或变量的实际实现,这些实现在std命名空间下; this file is also called the source file.该文件也称为源文件。

So if you only use using namespace std without #include <iostream> in your main.cpp file compiler will search std namespace in your main.cpp file, but it is not here.所以,如果你只使用using namespace std没有#include <iostream>在你main.cpp文件的编译器将搜索std命名空间在你main.cpp文件,但它是不是在这里。 You will get compiler error.你会得到编译器错误。

Now if you include this #include <iostream> line in your main.cpp , preprocessor will go iostream 's header file and copy the std namespace along with its code into our main.cpp .现在,如果您在main.cpp包含此#include <iostream>行,预处理器将转到iostream的头文件并将std命名空间及其代码复制到我们的main.cpp And linker will link the precompiled(as iostream is a SLT so it comes with compiler with prebuilt) source/implementation file of iostream to your main.cpp .和连接器将链接预编译(如iostream源/执行文件是一个SLT所以它带有编译器,预建) iostreammain.cpp Now to use functions or variables of iostream that sit under std namespace in main.cpp we have to use scope resolution operator(::) to tell the compiler that cout , cin and other functionalities of iostream sit at std namespace.现在要使用位于main.cpp std命名空间下的iostream函数或变量,我们必须使用作用域解析运算符 (::) 来告诉编译器coutciniostream其他功能位于std命名空间。 Thus we simply write like this: std::cin , and std::cout .因此我们简单地写成这样: std::cinstd::cout

Now typing std:: seems redundant to some people so they tell the compiler by using this using namespace std "Hey compiler, if you don't find any variables/functions/classes in global/current namespace go look in the std namespace."现在键入std::对某些人来说似乎是多余的,所以他们通过使用using namespace std告诉编译器“嘿编译器,如果在全局/当前命名空间中找不到任何变量/函数/类,请查看std命名空间。” Though this is not the best practice but that is another topic to discuss.虽然这不是最佳实践,但这是另一个要讨论的话题。 Therefore your assumption that std namespace contains all the definitions of all SLT's functions/classes/variables of C++ is not correct in most cases, but std namespace only contains the declaration from STL is the correct assumption.因此,你的假设,即std命名空间包含的所有SLT公司的C函数/类/变量++所有的定义是不是在大多数情况下是正确的,但std的命名空间只包含来自STL的声明是正确的假设。

Here is a dummy implementation how iostream libray is added to our code files: iostream.h :这是如何将iostream libray 添加到我们的代码文件中的虚拟实现: iostream.h

// This is header file that only contains the
// functions declarations.
namespace std_dum
{
    int add(int x, int y);

    int mult(int x, int y);
}

iostream_dum.cpp : iostream_dum.cpp :

// This is source file of iostream_dum.h header
// which contains the implementation of functions.

#include "iostream_dum.h"

namespace std_dum
{

    int add(int x, int y)
    {
        return x + y;
    }

    int mult(int x, int y)
    {
        return x * y; 
    }

}

main.cpp : main.cpp :

#include <iostream>
#include "iostream_dum.h"

int main()
{
    std::cout << std_dum::add(100, 200) << '\n';
    std::cout << std_dum::mult(100, 200) << '\n';

    return 0;
}

To see what happens to our main.cpp file after preprocessing run this command: g++ -E main.cpp iostream_dum.cpp .要查看预处理后我们的main.cpp文件会发生什么,请运行以下命令: g++ -E main.cpp iostream_dum.cpp

Here is roughly our main.cpp looks like:这里大概是我们的main.cpp样子:

namespace std_dum
{
    int add(int x, int y);

    int mult(int x, int y);
}

int main()
{
 std::cout << std_dum::add(100, 200) << '\n';
 std::cout << std_dum::mult(100, 200) << '\n';

 return 0;
}

namespace std_dum
{

    int add(int x, int y)
    {
        return x + y;
    }

    int mult(int x, int y)
    {
        return x * y;
    }

 }

For the sake of clarity, I discarded all the codes that the preprocessor copied from #include <iostream> .为了清楚起见,我丢弃了预处理器从#include <iostream>复制的所有代码。

Now it should be pretty clear.现在应该很清楚了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM