【问题标题】:Understanding the library functions in c++ [closed]了解 C++ 中的库函数 [关闭]
【发布时间】:2010-02-23 11:45:56
【问题描述】:

如果我想知道用标准 C++ 库编写的函数是如何工作的(不仅仅是 MSDN 描述)。我的意思是它如何分配、管理、释放内存并返回结果。你需要知道什么地方或什么才能理解?

【问题讨论】:

  • 哦,你需要知道 VMM 控制物理内存,内核如何管理虚拟内存,用户空间如何与内核通信,以及所有令人讨厌的东西。
  • 这个网站不适合这类非常广泛的问题。如果您想了解更多有关某些特定库函数的信息,请为其命名。要回答有关图书馆所有功能的这些问题,需要一本 300 页的书。此外,不清楚您是否专注于 Windows。
  • 作为一个问题而不是一个假设 - 您是在询问 STL(也许是关于容器模板的分配器参数以及它们如何工作,默认值是如何实现的)还是您在询问平台/实现详情?
  • 我正在寻找定义windows相关函数的源码。
  • @KennyTM:这不太对。大多数函数不需要需要知道你声称的所有低级的东西。该库经常使用自己,因此它的几乎所有部分都可以用标准 c++ 编写。因此,用“它使用 operator new”来回答“它是如何分配的”几乎在所有情况下都是正确的。

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


【解决方案1】:

您可以查看库标题。那里实际上实现了很多功能,因为该库是高度模板化的(并且模板通常需要在标头中实现)。头文件的位置取决于编译器,但您应该能够很容易地找到它们(例如,搜索名为 algorithm 的文件)。

您也可以要求编译器预处理您的代码以查看所有相关的标头(这将产生非常长的输出)。使用 GCC,您可以通过 g++ -E yoursource.cc 执行此操作。

如果您要查找的内容未在标头中实现,则需要库源,默认情况下通常不会安装这些源,甚至对于 MSVC 等商业编译器也不可用。查找 glibc(C 库)和 libstdc++(C++ 库),它们是 GCC 和其他一些编译器使用的。

在任何情况下,请注意标准库的实现往往相当神秘,因为在变量名称等中使用了很多下划线(以避免与用户的宏发生名称冲突),而且它们通常也被#ifdefs 感染和其他预处理器。

【讨论】:

    【解决方案2】:

    您需要了解用于编写 C++ 库的技术。获得Bjarne Stroustrup's 书是一个好的开始。此外,SGI 在适当的高抽象级别上提供了关于 STL 的非常详细的文档。

    如果你打算研究基于 Windows 的东西,你可能想study windows 库的系统部分。

    补充 windows:了解Posix 规范也很重要。

    【讨论】:

      【解决方案3】:

      首先是一些基本的数据结构原则,然后是关于分配器的注释和一些链接......

      STL 容器使用许多不同的数据结构。 map、set、multimap 和 multiset 通常被实现为具有红黑平衡规则的二叉树,例如,deque 可能(比知识更多)是数组中的循环队列,利用数组加倍或类似的增长模式.

      标准实际上并未定义任何数据结构 - 但指定的性能特征显着限制了选择。

      通常,您包含的数据直接包含在数据结构节点中,这些节点(默认情况下)保存在堆分配的内存中。您可以通过在指定容器时提供分配器模板参数来覆盖节点的内存源 - 稍后会详细介绍。如果您需要容器节点来引用(不包含)您的项目,请将指针或智能指针类型指定为包含类型。

      例如,在 std::set 中,节点将是二叉树节点,其中包含用于 int 和两个子指针的空间,以及库所需的元数据(例如红/黑标志)。二叉树节点不会在您的应用程序地址空间中移动,因此您可以根据需要将指向数据项的指针存储在其他地方,但并非所有容器都如此 - 例如向量中的插入将插入点上方的所有项目向上移动 1,并且可能必须重新分配整个向量,移动 所有 个项目。

      容器类实例通常非常小——通常只有几个指针。例如,std::set 等通常有一个根指针、一个指向最低键节点的指针和一个指向最高键节点的指针,可能还有更多元数据。

      STL 面临的一个问题是在多项目节点中创建和销毁实例而不创建/销毁节点。例如,这发生在 std::vector 和 std::deque 中。严格来说,我不知道 STL 是如何做到的 - 但显而易见的方法需要放置新的和显式的析构函数调用。

      Placement new 允许您在已分配的内存中创建对象。它基本上为您调用构造函数。它可以带参数,所以它可以调用复制构造函数或其他构造函数,而不仅仅是默认构造函数。

      要析构,您可以通过(正确键入的)指针显式调用析构函数。

      ((mytype*) (void*) x)->~mytype ();
      

      如果您没有声明显式构造函数,甚至对于不需要破坏的内置类型(如“int”),这也有效。

      同样,要将一个构造实例分配给另一个实例,您需要显式调用 operator=。

      基本上,容器能够相当容易地在现有节点中创建、复制和销毁数据,并且在需要时,元数据会跟踪节点中当前构建的项目 - 例如。 size() 指示当前在 std::vector 中构造了哪些项目 - 可能还有其他未构造的项目,具体取决于当前的 capacity()。

      编辑 - STL 可以通过(直接或有效地)使用 std::swap 而不是 operator= 来移动数据来优化。这在数据项是(例如)其他 STL 容器的情况下会很好,因此拥有大量引用的数据 - 交换可以避免大量复制。我不知道标准是否要求这样做,或者允许但不强制要求。但是,有一种众所周知的机制可以使用“特征”模板来做这种事情。默认的“特征”可以提供使用赋值的方法,而特定的覆盖可以通过使用交换方法来支持特殊情况类型。抽象将是一种移动,您不关心源中剩余的内容(原始数据、来自目标的数据等),只要它有效且可破坏。

      当然,在二叉树节点中,不需要这样做,因为每个节点只有一个项目,并且总是被构造的。

      剩下的问题是如何在节点结构中保留正确对齐和大小正确的空间以保存未知类型(指定为模板参数),而不会在创建/销毁节点时调用不必要的构造函数/析构函数。这在 C++0x 中会变得更容易,因为联合将能够保存非 POD 类型,从而提供方便的未初始化空间类型。在那之前,有一系列技巧或多或少地适用于不同程度的可移植性,毫无疑问,一个好的 STL 实现是一个值得学习的好例子。

      就我个人而言,我的容器使用空格换类型模板类。它使用特定于编译器的分配检查来确定编译时的对齐方式,并使用一些模板技巧从正确大小的字符数组、短数组、长数组等中进行选择。使用“#if defined”等选择了不可移植的对齐检查技巧,当有人向它抛出 128 位对齐要求时,模板将失败(在编译时),因为我还不允许这样做。

      如何实际分配节点?好吧,大多数(全部?)STL 容器都采用“分配器”参数,默认为“分配器”。该标准实现从堆中获取内存并将其释放到堆中。实现正确的接口,它可以用自定义分配器替换。

      这样做是我不喜欢做的事情,当然我的办公桌上没有 Stroustrups “C++ 编程语言”。您的分配器类需要满足很多要求,至少在过去(情况可能有所改善),编译器错误消息没有有帮助。

      Google 说你可以看这里……

      【讨论】:

        【解决方案4】:

        分配/释放内存的操作系统函数与 C++ 标准库并不真正相关。

        标准库容器将(默认情况下)使用 new 和 delete 作为内存,并且使用特定于编译器的运行时,几乎可以肯定管理自己的堆数据结构。这种方法通常更适合典型应用程序使用,其中特定于平台的操作系统堆通常更适合分配大块。

        应用程序堆将从操作系统堆中分配/释放内存,但是“如何?”什么时候?”是特定于平台和特定于编译器的详细信息。

        对于 Win32 内存管理 API,请看这里...

        http://msdn.microsoft.com/en-us/library/ms810603.aspx

        如果需要,我相信您可以找到 win64 等效项。

        【讨论】:

          【解决方案5】:

          我没有这本书,但根据它的描述,http://www.amazon.com/C-Standard-Template-Library/dp/0134376331 包括

          -使用和实现组件的实用技术

          这不是你想要的吗?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-04-11
            • 1970-01-01
            • 2014-12-14
            • 1970-01-01
            • 2013-04-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多