【问题标题】:How does the C++ standard library work behind the scenes?C++ 标准库是如何在幕后工作的?
【发布时间】:2020-05-18 01:22:15
【问题描述】:

在过去的几天里,这个问题一直困扰着我。我想知道标准库在功能方面是如何工作的。即使通过检查 LLVM 编译器提供的source code,我也无法在任何地方找到答案,对于像我这样的初学者来说,这是一段非常复杂的代码。

我在这里主要想了解的是 C++ 标准库是如何工作的。例如,让我们以fstream 头文件为例,它由一堆有助于写入和读取文件的函数组成。

它是如何工作的?它是否使用操作系统特定的 API(因为库是跨平台的),还是什么?而且,如果标准库可以做到这一点,我难道不应该在不调用标准fstream 文件的情况下也能处理一些文件吗(根据我的经验,我不能这样做)?

如果我不是以英语为母语的人,如果我的问题不清楚,我深表歉意:请随时修改此文本以使其更清晰。

【问题讨论】:

  • 标准库的接口是跨平台的。实施通常不是。是的当然是最终使用操作系统提供的设施。
  • 如果您不关心您的程序是否可移植,您也可以使用操作系统提供的 API。
  • 有不同的 STL 实现可用。 Visual Studio 有他们的。 GCC 有他们的,等等。通常大多数 C++ 已经可以跨平台工作,但是可以专门化代码以利用某些 OS 功能。
  • 我认为这是主题。一个清晰、写得很好的编程问题,有一个技术性的、非主观的答案。投票决定重新开放。
  • 您不需要使用 C++ 标准库。它只是为了让您的代码跨平台而存在。例如 - 要打开一个文件,您可以使用 std::fstream 或者您可以只调用标准库调用的操作系统特定函数(在 Windows 上,如果您使用 ASCII,则它是 CreateFileA。您甚至不需要头文件和您可以从作为 Windows 操作系统一部分的 kernel32.dll 创建链接库

标签: c++ c++-standard-library


【解决方案1】:

它是否使用操作系统特定的 API(因为库是跨平台的),还是什么?

在某些时候,会使用操作系统特定的 API。 fstream 实现不一定直接调用操作系统函数。它可能会使用其他类,这些类调用从 C 继承的函数等,但最终调用链将导致 OS 调用。 (是的,对于中级程序员来说,细节通常过于复杂。所以,作为一个自称是初学者,你的发现并不奇怪。)

该库是跨平台的,在您(C++ 程序员)端,无论平台如何,接口都是相同的。但是,它不是每个平台上的同一个库。每个平台都有自己的库,在 C++ 端公开相同的接口,但使用不同的操作系统调用。 (事实上​​,同一个平台可能有多个标准库,因为库实现是由您的工具链提供的,而不是由标准委员会提供的。)

而且,如果标准库可以做到这一点,我难道不应该在不调用标准fstream 文件的情况下也能处理一些文件吗(根据我的经验,我不能这样做)?

是的,您可以这样做。显然,您还不能做到,但通过一些练习和指导,您应该能够做到。标准库中的所有内容都可以在您自己的代码中重新创建。标准库(以及大多数库,就此而言)的重点是节省您的时间,而不是启用原本不可用的东西。例如,您不必为您编写的每个程序都实现文件流;它位于标准库中,因此您可以专注于项目中更有趣的方面。

【讨论】:

  • 我希望文字足够清晰。有人告诉我,我的写作风格对于非母语人士来说可能很粗糙。我确实试着把它调低一点。如果不够,请道歉。
【解决方案2】:

从某种意义上说,标准库是跨平台的,它的接口不会在平台之间改变,但它的实现会改变——或者实际上——如果你只使用 C++ 及其标准库,你可以用同样的方式编写代码Linux / Windows / MacOS / Android / Whatever 如果你找到了 C++对于支持您使用的语言功能的平台之一的编译器,您将能够为该平台编译代码而无需重写任何内容。

因此,尽管您可以使用库中的 std::vectorstd::fstream 或任何其他功能,而与您正在编写的平台无关,并期望函数定义、类型名称等看起来相同,但您不能期望您为装有 Windows 10 的 PC 编译的可执行文件,以便在装有 Android 的手机上运行。您甚至不能期望相同的可执行文件在同一台 PC 上运行但使用不同的系统 - 这就是我所说的“实现不同”的意思

造成这种差异的主要原因有两个:

  1. 具有不同架构(例如 x86-64 和 ARM)的处理器使用不同的指令集,因此需要将 C++ 源代码编译为完全不同的机器代码才能正常运行
  2. 具有相同架构处理器但操作系统不同的计算机在动态分配内存、创建文件、创建流、写入控制台、创建和调度线程等方面具有不同的方式 - 这是您系统功能的一部分通过标准库使用

如果你真的想要你可以使用HeapAlloc() 而不是operator new()CreateThread() 而不是stdlib 的std::thread 但这会迫使你在每次你想要编译它时都重写你的程序Windows 并使用目标平台的编译器重新编译它(并通过代理学习它的 API)。标准库通过抽象出那些系统调用,让您免于麻烦。

尤其是fstreamhere 是当今大多数 PC 内部使用的。

【讨论】:

    【解决方案3】:

    编译器只是一个创建可执行文件或库的程序。您可以使用编译器默认库来获得时间或编写自己的库。默认库与操作系统通信以进行文件操作或内存分配,并提供简单的标准类以允许开发人员仅编写一个代码,该代码可在编译器和库支持的所有目标平台上运行。如果你想编写自己的,你必须为你所有的目标操作系统编写每个函数。

    【讨论】:

      【解决方案4】:

      基本上,fstreamiostreamprintf 基于核函数 write() 工作。当你的代码调用printf(我们以printf为例)时,它最终会调用write()让内核处理IO的东西。之后,write() 返回,printf 返回,您的代码继续运行。

      所以如果你真的想知道printf在内部是如何工作的,你必须阅读内核的源代码。

      但你现在不应该这样做。

      对于初学者,在对计算机没有基本认识的情况下,不要试图深入。计算机是一个项目,就像一座建筑物。所以正确的学习方法是逐级学习。首先,学习如何使用砖和水泥建造建筑物,这是你现在应该做的。您不应该做的是您正在学习如何建造建筑物,这是您第一次尝试使用砖块,然后您对如何生产砖块感兴趣并开始专注于砖块,这是错误的方式学习 IT。

      如果你正在学习 C/C++,那就学吧。请记住,逐级学习。现在,知道如何使用printf 就足够了。

      【讨论】:

      • 回复:“基于内核函数write()”——也许,如果内核有它的话。但是要了解printf 在内部是如何工作的,首先要从printf 的源代码开始。
      猜你喜欢
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 2010-09-11
      • 2011-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多