繁体   English   中英

什么是STL?

[英]What is the STL?

我不是C ++程序员,很难理解网站上给出的解释。 我不了解容器或迭代器,也没有计划在不久的将来学习C ++。 所以用外行人的话说:什么是STL,它能为我做什么? 它与Python标准库或glibc相比如何?

要理解STL,至少要了解C ++的某些方面。 我会尽力解释它。 结构看似简单。 图书馆闪耀的地方在于如何使用它可以简化许多复杂的任务。 我会坚持一些非常简单的例子,因为其他任何东西都可能会让那些不懂C ++的人感到困惑,也因为我不想写一本小说。 ;)

首先,一些历史。 STL(标准模板库)是单独开发的,然后提交给C ++标准委员会考虑,使他们可以选择将其纳入语言。 但它并不是作为C ++标准的一部分开发的,因此,它的设计风格与C ++标准库的其他部分非常不同。 如果我记得我的古代历史,它也需要标准委员会了解STL并且习惯它。 当他们最初看到它时,他们并不太热衷于它,但过了一会儿,意识到它有多么强大和精心设计。 所以它被采用到语言中。 这一切都发生在20世纪90年代后期,因为语言接近ISO标准化。

STL的核心是提供您对标准库所期望的最基本功能:存储数据序列的能力以及处理这些序列的能力。

每种其他语言都有其标准库的Collections / Containers部分,包含动态数组(在Java中称为arraylists,在C#中为List,在C ++中为向量),链接列表,字典和其他常见数据结构的实现。

它们通常还提供一些穿越这些结构的机制。 (例如,枚举器或迭代器)

STL在C ++中提供了相同的功能,但它以异常优雅的方式提供,并带有一些有趣的抽象。

STL完全分为三个独立的组件:

  • 容器(如上所述,每种语言都有这些.Arrays,ArrayList,Dictionary,Set,LinkedList等。任何可以存储对象集合的数据结构都是C ++中的容器)
  • 算法(每种语言也都有某种形式。算法是处理元素序列的函数。)现在,假设序列是一个容器。 这有点简化,但我们会做到这一点。 算法有多种用途,包括允许您将函数应用于序列中每个元素的for_each()函数,或将函数应用于每个元素的相关transform() ,并将结果存储到单独的序列中(非常类似于函数式语言中的map操作),或者累积(类似于函数式语言中的fold),还有排序或搜索函数,以及允许复制整个序列的函数。
  • 最后,将容器和算法绑定在一起的粘合剂:迭代器。 如上所述,序列(算法的工作原理)与容器不完全相同。 容器中的元素当然构成一个序列,但容器中的前五个元素也是一个序列。 或者容器中的每个其他元素都是一个序列。 直接从文件流中读取的数据也可以视为序列。 即使是即时生成的数据(例如,斐波那契序列)也可以被视为一系列值。 序列不必映射到容器,甚至映射到内存中的数据,尽管这是最常用的。

请注意,这三个区域之间没有重叠。 容器存储(并拥有)数据,并生成迭代器。 迭代器允许您检查,修改和遍历数据。 并且算法在迭代器范围上运行

从概念上讲,迭代器有两个功能。 它指向一些数据,它可以在序列中移动(取决于迭代器类型,可以使用不同的移动操作。几乎所有迭代器都可以移动到下一个元素。有些也可以移动到前一个,有些可以向后和向前跳跃任意距离)。 如果你熟悉C,这听起来很像指针,这并非巧合。 迭代器被建模为指针的泛化,实际上,指针也是有效的迭代器。 所有STL算法都适用于指针以及“真实”迭代器。

这意味着是数据的任何序列可以通过一对迭代来表示:第一个迭代器指向在序列中的第一个元素,第二个点中的一个过去的序列的末尾。

这允许在循环中遍历序列的相当简单的语法:

std::vector<int> container;
for (iter it = container.begin(); it != container.end(); ++it)
{
  // perform some operations on the iterator (it) or the element it points to (*it)
  ++(*it); // increment the value the iterator points to
}

或者我们可以将算法应用于序列:

std::sort(container.begin(), container.end());

请注意,sort函数不知道或不关心它正在处理向量。 它传递了两个迭代器,它们可以是任何类型。 它们可以是指向数组,链表迭代器或任何其他有效迭代器类型的普通指针。

我们可以通过提供我们自己的比较器函数来概括排序函数(任何带有两个值的函数,如果第一个严格小于另一个,则返回true)

// sort in descending order, by passing in a custom comparer which uses greater than instead of less than
bool greater(int lhs, int rhs) { return lhs > rhs; }
std::sort(container.begin(), container.end(), greater);

当然,我们也可以只对矢量的前五个元素进行排序:

std::sort(container.begin(), container.begin()+5);

begin()和end()函数只是从容器中获取迭代器的便捷函数。 我们不必直接使用它们。

另一个很好的技巧是流也可以推广到迭代器中。 所以让我们从文件中读取所有整数,并将它们复制到一个数组(当然,数组是普通的C类型,因此它们不是正确的容器,也没有迭代器。但是指针工作正常)

int arr[1024];
std::ifstream file("something.txt");
// (note, this assumes <= 1024 integers are read)
std::copy(std::istream_iterator<int>(file) // create an iterator pointing to the current position in the file stream
        , std::istream_iterator<int>() // and our "end" iterator. When we reach the end of the stream, testing the two iterators for equality will yield true, and so the operation will halt
        , arr);

STL的独特之处在于它的灵活性和可扩展性。 它可以与C代码完全互操作(指针是合法的迭代器),它可以简单轻松地扩展(如果你愿意,你可以编写自己的迭代器类型。大多数算法采用比较器的自定义谓词,就像我上面展示的那样,和您可以定义自己的容器。也就是说,STL的三个支柱中的每一个都可以被覆盖或扩展,因此可以说STL更像是一种设计策略而不是任何东西。即使你使用STL代码也可以编写STL代码你自己的容器,迭代器和算法。并且因为这三个支柱中的每一个都与其他支柱完全分开,所以它们可以比大多数其他语言更容易更换,这三种职责混合在一起并由同一个类共享。算法不知道它所运行的序列存储在哪个容器(如果有的话)中。它只知道它已经传递的迭代器可以被解引用以访问数据本身。容器不必支持所有 标准算法。 它必须能够生成一对迭代器,然后所有功能都是免费的。

相比之下,比如Java,每个集合类必须实现自己的搜索,自己的排序,自己的一切。 在C ++中,我们只需要一个find()实现。 它需要两个迭代器和要查找的值,并遍历查找值的序列。 因此,它适用于任何容器类型,甚至是我自己定义的容器类型。

STL的另一个显着特点是在使用它时几乎没有性能损失。 C ++模板在编译时都被替换,产生的代码可以像在C中手动编码所有内容一样进行优化。上面的sort函数会丢失一些性能,因为我将一个函数指针传递给它作为我的自定义比较器,通常不能内联,但如果我们这样定义它可以修复:

struct greater {
    bool operator()(int lhs, int rhs) { return lhs > rhs; }
};
std::sort(container.begin(), container.end(), greater());

现在我们不再传递函数指针,而是一个对象。 和成员函数(例如操作者()) 可以被内联。 因此,这种排序功能将与您在C中手动编码的任何功能一样高效。

而且,它甚至不必为sort函数添加任何复杂性。 实际上,sort恰好有两个重载。 一个采用比较器功能,一个不采用比较器功能。

sort函数不需要知道它是传递函数指针还是对象。 只要语法“X(a,b)”有效,其中X是作为比较器传递的值,而a,b是要比较的元素,sort函数的相同实现将起作用。 并且因为我的greater对象重载了operator(),所以该语法对于此对象和我们之前传递的函数指针都是有效的。 STL代码通过利用这样的技巧免费获得许多功能。 由于C ++模板的工作方式,函数的相同实现适用于非常不同的参数类型。

STL是标准模板库。 它是C ++标准库的子集。

STL提供有用算法和容器的通用实现。

容器提供了在程序中存储数据的任何简单方法,然后查找,排序和执行对该数据的其他计算。

标准模板库是在C ++标准化之前用C ++编写的库。 它包括很酷的东西,如排序算法和容器(和迭代器,使用这些功能)。

在1998年标准化时, C ++标准库的部分内容基于STL的部分内容; 它是自进化以来(通过2003标准,特别是现在使用C ++ 0x)。

  • C ++标准库由各种编译器供应商(及其朋友)实现,并附带您最喜欢的工具链。
  • 这就是你实际上可能会使用的:STL现在已经过时了。

请注意,许多程序员(包括一些多产的书籍作者) 仍然习惯使用术语 “STL”来引用C ++标准库(或最初基于STL的部分),即使这是不正确的。 只要你知道技术上的区别,你应该没问题。

希望这可以帮助。

如果您不是C ++程序员,标准模板库的实现对您来说毫无价值。 但是,这些想法超越了任何编程语言。

它是一个数据结构库(例如,地图,列表,向量等)。 它包括用于抽象遍历这些数据结构的迭代器,以及用于对它们进行操作的算法。 其他语言也使用这些想法,所以如果你用一种语言学习它们,他们就会熟悉其他语言。

STL是标准模板库。 它是一个可以使用的函数和类库。 它具有许多基本计算机科学的基本算法和数据结构。 如果您打算继续使用C ++,那么您应该计划学习这个或另一个资源库。

该代码被世界上许多人使用,因此您可以放心地对代码进行了充分测试并且众所周知。

它是一个使某些事情变得更容易的库,比如字符串操作,向量,链表等等.STL可以让你不必编写一些低级代码,让你更专注于应用程序代码。

暂无
暂无

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

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