由于命名空间std已经有包含函数定义的c ++库(如果我是对的),那么为什么我们在它上面包含头文件?由于命名空间std包含c ++标准库,因此我没有理由单独包含它的声明。
答案 0 :(得分:7)
执行#include <iostream>
时,会导致源文件中包含一组类和其他内容。对于iostream和大多数标准库头文件,他们将这些内容放在名为std
的名称空间中。
所以#include <iostream>
的代码看起来像这样:
namespace std {
class cin { ... };
class cout { ... };
class cerr { ... };
class clog { ... };
...
}
所以在这一点上,你可以编写一个看起来像这样的程序:
#include <iostream>
int main() {
std::cout << "hello\n";
return 0;
}
现在,有些人认为std::cout
过于冗长。所以他们这样做:
#include <iostream>
using namespace std;
int main() {
cout << "hello\n";
return 0;
}
就个人而言,我建议不要这样做,如果您确实认为std::cout
过于冗长,那么我建议您使用较小的using
语句。
#include <iostream>
using std::cout;
int main() {
cout << "hello\n";
return 0;
}
如果您想知道为什么我会推荐using namespace std
,那么我会转发给stackoverflow上的以下两篇帖子:
答案 1 :(得分:5)
编译器本身没有任何命名空间中的东西的定义(无论是std
还是其他命名空间)。这是源文件和头文件的作用。
using namespace std;
告诉编译器的是“如果在当前命名空间中找不到某个名称,请同时查看std
命名空间”。
#include <iostream>
告诉编译器,您希望源代码中包含名为iostream
的标头内容。这将为编译器提供执行cin
,cout
和许多其他相关功能的代码。此文件的内容声明为namespace std { ... all the stuff goes here ... }
。
命名空间的使用允许在namespace math;
工作的其他人不必担心“嗯,我现在该做什么,我需要一个入口数量的计数器,我们称之为cin
- 但坚持下去,是否曾经在任何地方使用过?“
这可能不是最好的例子,但在大型项目中,跟踪事物及其名称变得越来越难。 C ++是一种用于数百万行代码的大型项目的语言 - 现在,如果你使用了某个特定的名字,它就会变得难以记住。命名空间确保您不必在特定命名空间之外担心它。
(哦,在我的代码中,我倾向于不使用using namespace std;
,而是写std::cout << "Hello, World!" << std::endl;
- 这有助于明确我在这里使用的cout
是std
一个,而不是别的。当你有几个具有相似内容的命名空间时,这是特别有用的,比如我自己的编译器,我的编译器有它的功能,std
命名空间提供一些东西和llvm
编译器 - 如果我在代码的开头粘贴using namespace llvm;
,那么很难跟踪Type* p = ...
;是来自LLVM还是我自己的某些部分代码。)
答案 2 :(得分:0)
...为什么我们在它上面包含头文件?
是的,这里有一些很大的混乱。
命名空间是一种将函数名称等符号分类或组合在一起的方法。
命名空间旨在防止不同软件组件(如库)之间的名称冲突。
作为标准语言一部分的函数分组在命名空间std
下。
C ++语言提供语句以减少使用命名空间时的键入量。其中之一是using
声明。
编写程序时,编译器不需要自动包含所有符号定义,例如函数声明。您需要告诉它您计划使用哪些功能。
例如,我可以在不使用sort
组中的advance
或algorithm
函数的情况下编写程序。因此,我不会包含头文件algorithm
。
C ++语言旨在“使用您需要的东西”,换句话说,我们可以通过仅包含我们需要的功能来创建小程序。
顺便说一下,除了你正在使用的平台外,还有很多其他平台。
某些平台需要适合小内存区域,并且可能没有键盘或显示器(例如嵌入式控制器)。
所以请记住,C ++被定义为支持从小型和受约束到大型且几乎无约束的系统的平台。
因此,对&#34;的要求仅包括您需要的内容&#34;主题。
总之,由于C ++语言不会自动地神奇地提供整个库的定义,包括模板库,因此需要告诉编译器要使用哪些函数组。这样可以更快地进行编译,因为只指定了所需的头文件。
注意:一些商店和图书馆用品喜欢使用 Monolith 包含系统。这意味着它们有一个包含整个库的包含文件,无论您使用的是一个函数还是多个函数。 windows.h
是一个典型的例子。一个不利之处在于,当一个头文件被更改时,一切都需要重建。使用分隔的包含文件,只需要重建包含已更改的头文件的组件。
答案 3 :(得分:0)
使用预处理器指令#include与c ++本身一样古老。并且它不会更快消失。在C ++命名空间中不会将任何内容导入到您的程序中,它只是定义了特定头文件函数的范围。因此,两者都是必需的。 Click here了解为何使用命名空间。
答案 4 :(得分:0)
您的问题是:namespace std
具有iostream
库的所有函数/类的定义。因此,只需使用using namespace std
就足以调用或使用cout
或iostream
库的所有其他功能。为什么我们必须使用第#include <iostream>
行?似乎是多余的。
大致上,我们可以认为iostream
库具有两个文件:标头和实现/源文件。这两个文件具有一个名为std
的命名空间。头文件仅包含iostream
库将要使用的类或函数或变量的声明或正向声明,并且这些声明或正向声明位于std
命名空间下。实现文件包含类,函数或变量的实际实现,并且这些实现位于std
命名空间下;此文件也称为源文件。
因此,如果您在using namespace std
文件编译器中仅使用#include <iostream>
而没有main.cpp
,则会在std
文件中搜索main.cpp
命名空间,但是这里没有。您将得到编译器错误。
现在,如果您在#include <iostream>
中加入这一行main.cpp
,则预处理器将转到iostream
的头文件,并将std
名称空间及其代码复制到我们的{ {1}}。并且链接程序会将main.cpp
的预编译(因为iostream
是SLT,因此它带有预编译的编译器)源/实现文件链接到您的iostream
。现在要使用位于main.cpp
中iostream
命名空间下的std
的函数或变量,我们必须使用范围解析运算符(::)告诉编译器main.cpp
,{ {1}}和cout
的其他功能位于cin
命名空间。因此,我们只需这样写:iostream
和std
。
现在对某些人来说,键入std::cin
似乎是多余的,因此他们通过使用此std::cout
告诉编译器“嘿,如果您在全局/当前名称空间中找不到任何变量/函数/类,在std::
名称空间中查看。”尽管这不是最佳实践,但这是另一个需要讨论的话题。因此,您对using namespace std
命名空间包含C的所有SLT函数/类/变量的所有定义的假设在大多数情况下是不正确的,而std
命名空间仅包含STL的声明是正确的假设。 / p>
这是一个伪实现,如何将std
libray添加到我们的代码文件中:
std
:
iostream
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
:
// 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
文件会发生什么,请运行以下命令:#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;
}
。
这里的main.cpp
大致如下:
g++ -E main.cpp iostream_dum.cpp
为清楚起见,我丢弃了预处理器从main.cpp
复制的所有代码。
现在应该很清楚了。