【C++】——【 STL简介】——【详细讲解】

目录

​编辑

[1. 什么是STL](#1. 什么是STL)

[2. STL的版本](#2. STL的版本)

[3. STL的六大组件](#3. STL的六大组件)

1.容器(Container):

2.算法(Algorithm):

3.迭代器(Iterator):

4.函数(Function):

5.适配器(Adapter):

6.分配器(Allocator):

[4. STL的重要性](#4. STL的重要性)

[5. 如何学习STL](#5. 如何学习STL)

[6. STL的缺陷](#6. STL的缺陷)

总结


专栏:C++学习笔记

1. 什么是STL

STL(Standard Template Library,标准模板库)是C++标准库的重要组成部分。它不仅是一个可复用的组件库,而且是一个包含数据结构与算法的软件框架。STL为开发者提供了多种高效、灵活且可扩展的模板化工具,使得复杂的程序开发变得更加简单和高效。

代码示例 :使用STL的vector容器

复制代码
#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

  • vector就像一个可以自动扩展的数组,你可以随意添加或删除元素。
  • 在上面的例子中,创建了一个包含数字1到5的vector,并输出这些数字。

2. STL的版本

STL经历了多个版本的发展,不同版本有不同的特点和应用场景:

  • 原始版本:由Alexander Stepanov和Meng Lee在惠普实验室完成的原始版本。这个版本是开源的,允许任何人任意使用、修改和传播。
  • P. J. 版本:由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用。这一版本不能公开或修改,其缺陷在于可读性较低,符号命名比较怪异。
  • RW版本:由Rouge Wage公司开发,继承自HP版本,被C++ Builder采用,也不能公开或修改,但可读性一般。
  • SGI版本:由Silicon Graphics Computer Systems公司开发,继承自HP版本,被GCC(Linux)采用。这个版本可移植性好,可公开、修改甚至商业使用。从命名风格和编程风格上看,阅读性非常高。

小李很执着理解

  • 不同版本的STL是由不同的人和公司开发的,有些版本是开源的,有些版本是商业化的。
  • 学习STL时主要参考SGI版本,因为它的可读性和移植性都很好。

3. STL的六大组件

STL由以下六大组件组成:

1.容器(Container)

用于存储和组织数据的对象,如vectorlistdequesetmap等。

代码示例 :使用map容器

复制代码
#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> age;
    age["Alice"] = 30;
    age["Bob"] = 25;

    for (const auto& pair : age) {
        std::cout << pair.first << " is " << pair.second << " years old." << std::endl;
    }

    return 0;
}

运行结果

小李很执着理解

map就像一本字典,可以根据"键"(如名字)查找对应的"值"(如年龄)。

在上面的例子中,创建了一个名字和年龄的对应关系,并打印出来。

2.算法(Algorithm)

用于操作容器中的数据的函数集合,如排序、查找、复制、删除等。

代码示例 :使用sort算法

复制代码
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {4, 2, 5, 1, 3};
    std::sort(numbers.begin(), numbers.end());

    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

sort算法可以对容器中的元素进行排序。

在上面的例子中,对一个包含随机数字的vector进行了排序,并打印出了排序后的结果。

3.迭代器(Iterator)

用于在容器中遍历元素的对象,类似于指针。常见的有forward_iteratorbidirectional_iteratorrandom_access_iterator等。

代码示例 :使用iterator遍历vector

复制代码
#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    std::vector<int>::iterator it;

    for (it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

iterator类似于指针,可以用来遍历容器中的元素。

在上面的例子中,使用iterator遍历了一个vector,并打印出了每个元素。

4.函数(Function)

STL提供了一些函数对象和仿函数,用于实现自定义的算法行为。

代码示例 :使用greater仿函数

复制代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main() {
    std::vector<int> numbers = {4, 2, 5, 1, 3};
    std::sort(numbers.begin(), numbers.end(), std::greater<int>());

    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

greater是一个仿函数,用来实现降序排序。

在上面的例子中,使用greater仿函数对vector进行了降序排序,并打印出了排序后的结果。

5.适配器(Adapter)

用于修改容器或仿函数行为的组件,如stackqueuepriority_queue等。

代码示例 :使用stack适配器

复制代码
#include <iostream>
#include <stack>

int main() {
    std::stack<int> s;
    s.push(1);
    s.push(2);
    s.push(3);

    while (!s.empty()) {
        std::cout << s.top() << " ";
        s.pop();
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

stack是一种先进后出(LIFO)的数据结构,就像叠盘子,最后放的盘子最先拿出来。

在上面的例子中,往stack中添加了三个数字,并按顺序取出了这些数字。

6.分配器(Allocator)

用于管理内存分配和释放的组件。

代码示例:自定义分配器

复制代码
#include <iostream>
#include <memory>
#include <vector>

template<typename T>
struct SimpleAllocator {
    typedef T value_type;

    SimpleAllocator() = default;

    template<typename U>
    SimpleAllocator(const SimpleAllocator<U>&) {}

    T* allocate(std::size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }

    void deallocate(T* p, std::size_t) noexcept {
        ::operator delete(p);
    }
};

int main() {
    std::vector<int, SimpleAllocator<int>> vec = {1, 2, 3, 4, 5};

    for (int num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

分配器负责管理内存的分配和释放,可以自定义来满足特定需求。

在上面的例子中,实现了一个简单的分配器,并用它来创建一个vector,然后打印出了vector中的元素。

知识点:STL的六大组件各有用途,组合使用可以解决复杂的数据处理问题。

4. STL的重要性

STL在C++开发中占有重要地位,其重要性主要体现在以下几个方面:

在笔试中:STL提供的高效算法和容器常常在编程题中使用,如二叉树层序打印、重建二叉树、用两个栈实现一个队列等。

代码示例:用两个栈实现一个队列

复制代码
#include <iostream>
#include <stack>

class Queue {
private:
    std::stack<int> stack1, stack2;

public:
    void enqueue(int x) {
        stack1.push(x);
    }

    int dequeue() {
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }

        if (stack2.empty()) {
            throw std::out_of_range("Queue is empty");
        }

        int top = stack2.top();
        stack2.pop();
        return top;
    }
};

int main() {
    Queue q;
    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);

    std::cout << q.dequeue() << " "; // 输出1
    std::cout << q.dequeue() << " "; // 输出2
    std::cout << q.dequeue() << std::endl; // 输出3

    return 0;
}

运行结果

小李很执着理解

通过使用两个栈,可以实现一个队列的功能,先进先出(FIFO)。

在上面的例子中,创建了一个队列,往其中添加了三个数字,并按顺序取出了这些数字。

在面试中:掌握STL是衡量C++开发者能力的重要标准之一。面试官常常通过STL相关问题考察候选人的算法能力和代码实现能力。

在工作中:STL使得开发者无需重复实现基础数据结构和算法,可以专注于业务逻辑的实现,大幅提升开发效率和代码质量。

网上有句话说:"不懂STL,不要说你会C++"。这句话充分体现了STL在C++开发中的重要性。

5. 如何学习STL

学习STL可以分为三个阶段:能用、明理、能扩展。

能用:首先要掌握STL的基本用法,了解各类容器、算法和迭代器的使用方法,并能够在实际开发中应用。

代码示例 :使用vectorsort

复制代码
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {4, 2, 5, 1, 3};
    std::sort(numbers.begin(), numbers.end());

    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

学习STL的第一步是能够正确使用它的各种容器和算法。

在上面的例子中,使用了vector和sort,并打印了排序后的结果。

明理:深入理解STL的内部实现原理,了解各组件的设计思想和工作机制,掌握常见问题的解决方法。

知识点 :例如,了解vector如何管理动态数组的内存,如何在内部实现扩容等。

能扩展:在掌握基础知识的基础上,能够根据具体需求对STL进行扩展或优化,如自定义分配器、实现特定算法等。

代码示例:自定义分配器

复制代码
#include <iostream>
#include <memory>
#include <vector>

template<typename T>
struct SimpleAllocator {
    typedef T value_type;

    SimpleAllocator() = default;

    template<typename U>
    SimpleAllocator(const SimpleAllocator<U>&) {}

    T* allocate(std::size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }

    void deallocate(T* p, std::size_t) noexcept {
        ::operator delete(p);
    }
};

int main() {
    std::vector<int, SimpleAllocator<int>> vec = {1, 2, 3, 4, 5};

    for (int num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果

小李很执着理解

学习STL的高级阶段是能够根据需求进行扩展,比如自定义分配器。

在上面的例子中,实现了一个简单的分配器,并用它来创建一个vector。

知识点 :学习STL不仅要会用,还要理解其原理,进而能够根据需求进行扩展。

6. STL的缺陷

虽然STL功能强大,但也存在一些缺陷:

更新速度慢:STL库的更新速度较慢。自C++98之后,中间的C++03版本仅做了一些修订,直到C++11才有进一步的更新。

缺乏线程安全:STL目前不支持线程安全。在并发环境下,开发者需要自己加锁,而且锁的粒度较大。

内部复杂:STL极度追求效率,导致内部实现比较复杂,如类型萃取、迭代器萃取等机制。

代码膨胀问题 :由于模板语法的特性,STL的使用会导致代码膨胀,例如使用vector<vector<vector<int>>>这样的嵌套容器会生成多份代码。

小李很执着理解

STL虽然强大,但也有一些问题,比如更新慢、不支持线程安全、内部复杂和代码膨胀。

了解这些缺陷可以帮助在使用过程中规避潜在的问题,并根据需求做出合理的取舍和优化。

总结

总结来说,STL是C++开发中不可或缺的重要工具。掌握STL不仅能够大幅提升开发效率和代码质量,还能帮助开发者更深入地理解C++语言的精髓。在学习和使用STL的过程中,虽然会遇到一些挑战和问题,但其带来的便利和效率提升是无可替代的。

相关推荐
for_ever_love__5 小时前
UI学习:UISearchController基础了解和应用
学习·ui·ios·objective-c
心中有国也有家5 小时前
GE图引擎深度解析——CANN的计算图优化与执行引擎
人工智能·pytorch·python·学习·numpy
isyangli_blog6 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008116 小时前
FastAPI APIRouter
开发语言·python
Benszen6 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆6 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木6 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
GHL2842710906 小时前
换脸工作流学习
学习·ai
MC皮蛋侠客6 小时前
C++17 多线程系列(五):C++17 并行算法——从串行到并行的零成本迁移
c++·多线程
_李小白7 小时前
【android opencv学习笔记】Day 28: 滤波算法之中值滤波器
android·opencv·学习