【问题标题】:Why does dont you have to #include<vector>, if you already include using name space std?如果您已经包含使用名称空间标准,为什么不必#include<vector>?
【发布时间】:2019-10-09 12:19:13
【问题描述】:

我一直在学习面向对象的计算,尤其是迭代器和标准模板库等。

如果你这么写,我似乎不太明白为什么

std:vector<int> - //blah, a vector is created.

但是,在某些情况下你需要写

#include <vector> //to include vector library

这是为什么? 我们通常写“using namespace std”的标准库是否已经包含向量库?

当我删除定义文件#include 时,计算机无法识别我的向量变量。

但是,我看到在某些情况下,很多人使用了向量函数而没有通过 std::vector 实际声明它???

std::vector<int>::iterator pos;
std::vector<int>coll;

这是其他人使用的代码,它似乎可以工作?

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>

using namespace std;

int main() {
vector<int>::iterator pos;
vector<int>coll;
}

// 这对我有用,但我想了解为什么这个有效而另一个无效。

【问题讨论】:

  • using namespace std; // this is a using directive telling the compiler to check the std namespace when resolving identifiers with no prefix -- learncpp.com/cpp-tutorial/…
  • 所有种情况下,您需要使用#include &lt;vector&gt;,而不仅仅是因为它不能编译。另一个标题可能包含它,但不能保证。
  • std:vector&lt;int&gt; 一个分号是label

标签: c++ vector stl stdvector


【解决方案1】:

using namespace std; 指令只是说“对于 std 命名空间中的任何内容我知道,您可以省略 std:: 前缀”。但是如果没有#include &lt;vector&gt;(直接或间接通过其他#include),编译器一开始就不知道std::vector 的存在。

标头为您提供各种类和 API 的声明(在某些情况下,还提供定义); using namespace 声明只是消除了使用命名空间前缀明确限定对它们的引用的需要。

您仍然需要执行#includes 的原因是声明的冲突消除(您不想只包含所有可能的包含文件,因为其中一些可能具有某些名称的冲突定义),并且编译性能(#includeing the world 意味着要编译的额外代码有很多千字节(如果不是兆字节),其中绝大多数您不会实际使用;将其限制为您实际需要的标头意味着更少的磁盘 I/O,更少的内存和更少的 CPU 时间来执行编译)。

为了将来参考,“我们通常写'using namespace std;'”表示你已经被教坏习惯。 using namespace std;is frowned upon in production code.

【讨论】:

  • 你为什么说“我知道的任何事情”?
  • 其实我现在明白你的意思了!非常感谢!!
  • @HasanHussaini:在这种情况下,“我”指的是编译器;该指令说“编译器知道的关于std 的任何内容都不需要由程序员用std 限定”。我用“我”和“你”说话有点不正式,如果混淆了,请见谅。
  • 这只能回答一半的问题。为什么其他代码示例不需要包含?
  • @MooingDuck:我顺便提过,当我说“没有#include &lt;vector&gt;(直接或间接通过其他#include)时,编译器首先不知道std::vector 存在。”为什么某些代码示例在没有包含的情况下工作的答案是它们包含了一些其他标头,而这些标头又包含&lt;vector&gt;。如果他们不这样做,则没有std::vector 的定义,并且代码因未定义类型而失败。它必须包含在内,但这并不意味着您直接包含它(也就是说,您应该避免标题更改破坏编译)。
【解决方案2】:

如果您已经使用名称空间标准包含了,为什么不必#include?​​p>

仅当您使用该标头中的声明时,您才必须包含 &lt;vector&gt;。否则你不需要包含它。你永远需要using namespace std;

如果你写,似乎不太明白为什么

std:vector<int> - //blah, a vector is created.

但是,在某些情况下你需要写

#include <vector> //to include vector library

如果您创建 std:vector&lt;int&gt; 对象,您总是必须包含 &lt;vector&gt;

我们通常写“使用命名空间std”的标准库是否已经包含向量库?

不,标准库不使用using namespace std;。如果是这样,那将使使用 std 命名空间的全部意义失效。

当我删除定义文件#include时,计算机无法识别我的向量变量。

这是因为您不能声明尚未定义的类型的变量。 std::vector的定义在&lt;vector&gt;

【讨论】:

    【解决方案3】:

    如果你已经包含使用,为什么不包含 命名空间标准

    看看这个网址:https://en.cppreference.com/w/cpp/header

    有 100 多个头文件可供您使用。

    恕我直言,您遇到的困惑是,这些相同的 100 多个标头也可供标头作者使用,并且他们还可以访问通常未在标准中发布的标头。结果是,例如,当您或我包含 时,包含的某些间接部分也可能“拉入”

    我建议您不要在代码中添加“使用命名空间标准”。它的使用并没有故意导致 的“隐藏/间接”包含,并且可能不会在下一个实现中。

    我正在使用 g++v7.3。我很快就会升级到当前的 g++(我认为是 9.x?)除非您明确包含它,否则您不能依赖包含它。

    这对我有用,但我想了解为什么这个有效以及 另一个没有。

    只是运气......我认为不好,如果你因此而养成多个坏习惯。


    如果你的编译器支持 -std=c++17 或更好,它有一个我喜欢的新特性。新功能允许我在包含头文件之后立即指定该库中我特别需要的函数。它看起来像这样:

    #include <iostream>
    using std::cout, std::cerr, std::endl, std::flush,
          std::hex, std::dec, std::cin;
    
    #include <iomanip>
    using std::setw, std::setfill;
    
    #include <string>
    using std::string, std::to_string;
    
    #include <thread>
    using std::thread, std::this_thread::sleep_for;
    
    #include <vector>
    using std::vector;
    

    您自己的库也可以类似处理:

    #ifndef                 DTB_ENG_FORMAT_HH
    #include "../../bag/src/dtb_eng_format.hh"
    using DTB::EngFormat_t;
    #endif
    
    #ifndef                 DTB_PPLSEM_HH
    #include "../../bag/src/dtb_pplsem.hh"
    using DTB::PPLSem_t;
    #endif
    
    #ifndef                 DTB_ENG_FORMAT_HH
    #include "../../bag/src/dtb_eng_format.hh"
    #endif
    
    #ifndef                 DTB_ASSERT_HH
    #include "../../bag/src/dtb_assert.hh"
    #endif
    

    我尝试跟踪其中的一小部分,并将它们收集到一个文件中。当我开始一项新工作时,我会使用更大的列表,并简单地删除“未使用”的功能(当我想发布我的工作时)。

    【讨论】:

    • 感谢您的提醒。在自己的 VS 设置中,有 &lt;filesystem&gt; 拉入 &lt;vector&gt;,其中不包括 &lt;vector&gt; 的风险是以希望在代码的生命周期内不会从 &lt;filesystem&gt; 拉出为代价的。
    【解决方案4】:

    #include &lt;some_file&gt; 只是将#include 指令替换为文件“some_file”的内容。

    对于#include &lt;vector&gt;,文件“vector”包含std命名空间中类模板vector的定义。要声明一个类的实例,该类的定义必须对编译器可见,因此要声明std::vector&lt;int&gt; foo,您必须直接或间接通过#includeing 另一个#includes 的文件来声明#include &lt;vector&gt;

    那么为什么有些代码示例必须#include &lt;vector&gt; 而有些则不需要呢?嗯,他们都这样做。有些人可能没有明确地#include 它,但他们必须#include 另一个执行#include &lt;vector&gt; 的文件。

    当然,在许多例子中,sn-ps 人们会为了简洁而简单地省略#includes。如果没有正确的 #includes,代码将无法编译,但它们会使代码更长,并且可能会分散作者试图提出的观点。


    语句using namespace std; 只是告诉编译器它应该在std 命名空间中搜索它在当前命名空间中找不到的任何非限定名称。这意味着编译器可以通过名称vectorstd::vector 找到vector 类。

    【讨论】:

    • 这只是清楚地回答了一半的问题,也只是暗示了另一半的答案。为什么其他代码示例不需要包含?
    【解决方案5】:

    首先,std:vector&lt;int&gt; - //blah, a vector is created. 无法编译,因为您使用了一个冒号 :,这意味着这里的 std 是一个 label 声明。并且标签名称不能是vector&lt;int&gt;。所以我猜你的意思是:std::vector&lt;int&gt;

    其次,您可能知道vectoriostream、...是分别在标头&lt;vector&gt;&lt;iotream&gt; 中定义的库类型...要使用这些类型,您必须首先直接包含这些标头,或者间接的。

    namespace std 在 C++ 中是一组标识符,用于减少命名冲突的可能性。在现代 C++ 中,C++ 标准库中的所有功能现在都在命名空间 std(标准的缩写)中定义。

    例如std::cout;此标识符在命名空间std 中声明,其类型为ostream。所以你必须首先包含iostream,这样编译器才能看到ostream对象是什么,然后告诉编译器这个对象在哪里声明? in namespace std。因此,仅包含 iostream 是不够的,因此您要么添加声明 cout 的命名空间 std 的全部内容,要么通过完全限定它明确告诉编译器声明 cout 的位置:

    #include <iostream> // contains output/input library types definitions
    using std::cout; // ok add only cout definition to the program not the whole content of std.
    using namespace std; // contains cout, cin, vector....
    

    【讨论】:

      【解决方案6】:

      向量是 C++ STL 的一部分,是的,但是您需要包含 &lt;vector&gt; 头文件才能使用它。如果您想使用 STL 字符串,这与您需要 #include &lt;string&gt; 的原因相同。包含这些头文件后,您需要在声明向量或字符串之前使用 std:: 命名空间标识符,以便编译器知道您声明的内容是 C++ STL 的一部分,而不是“基础”C 的内置内容或 C++。

      基本上,using namespace std 所做的就是让您能够在stringvector 或其他任何东西之前删除std:: 限定符。不建议这样做,here's 一篇简要解释了为什么你不应该使用它的文章。相反,如果您想清理代码并且不想在每次打印到控制台时都输入 std::,那么请考虑导入单个标识符,例如 using namespace std::cout

      希望这会有所帮助。

      【讨论】:

      • 这只能回答一半的问题。为什么其他代码示例不需要包含?
      • 正如其他答案中提到的,其他人的代码可能包含具有向量的标头,但不能保证
      • 来自quora.com/In-C-what-is-stl-and-std-How-are-they-different 的 Sergey Zubkov:“STL”(“标准模板库”)是 1990 年代初期惠普的 C++ 库的名称。它在 1998 年对 C++ 标准库的开发产生了巨大的影响,这就是它的失败:HP 认为没有必要维护 STL,它在 SGI 的网站上被遗弃了十多年,现在已经消失了。” ....您的符合标准的编译器(例如 Lubuntu 19.10 上的 g++ 9.2.1)带有“C++ 标准库”,您应该使用它(而不是废弃的 STL)。即包含“向量”。
      猜你喜欢
      • 2022-12-03
      • 2012-09-19
      • 1970-01-01
      • 2015-03-29
      • 2011-09-30
      • 2016-07-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-24
      相关资源
      最近更新 更多