C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】

文章目录

    • STL 标准模板库
      • 1、 STL简介
      • 2、STL容器的类别
      • 3、STL迭代器的类别
      • 4、STL算法的类别
      • 5、泛型编程(generic programming)
      • 6、C++模板(template)
        • 6.1 函数模板(function template)
        • 6.2 类模板(class template)

STL 标准模板库

推荐 C++ 学习资料网站:C++ 参考手册

1、 STL简介

什么是STL:

  • ⼀个强⼤的、可复⽤的、⾃适应的泛型类和函数集合
  • 使⽤C++ 模板(templates)实现
  • 实现了常⻅的数据结构(data structures)和算法(algorithms)
  • 庞⼤的类库
  • 俄裔美籍程序员:Alexander Stepanov 1994年开发

容器,算法,迭代器是独立设计的,但是它们之间配合的很好

  • 容器(containers)
    • 各种对象或原始类型的集合
    • array、vector、deque、stack、set、map等
  • 算法(algorithms)
    • 处理容器元素序列的各种函数
    • find、max、count、accumulate、sort等
  • 迭代器(iterators)
    • 从容器中⽣成元素的序列
    • forward、reverse、by value、by reference、constant等

sort()算法需要使用元素的序列,这个时候需要使用到标准模板库中迭代器,使用 vec.begin() 和 vec.end() 可以将vec 的第一个元素到最后一个元素传给 sort,

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第1张图片

accumulate(vec.begin(), vec.end(), 0) 中三个参数的表示是:vec.begin(), vec.end()表示迭代器,从哪里开始到哪里结束,0:表示累加的初始值,

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第2张图片

2、STL容器的类别

  • 序列式容器(sequence containers)
    • array、vector、list、forward_list、deque
  • 关联式容器(associate containers)
    • set、multi set、map、multi map
  • 容器适配器(container adapters),无法使用迭代器
    • stack、queue、priority queue

3、STL迭代器的类别

  • 输⼊迭代器(input iterators)
    • 从容器到程序(对数据只读访问)
  • 输出迭代器(output iterators)
    • 从程序到容器(对数据只写访问)
  • 前向迭代器(forward iterators)
    • 向前推进迭代器(读写)
  • 双向迭代器(bi-directional iterators)
    • 向前、向后推进迭代器(读写)
  • 随机访问迭代器(random access iterators)
    • 直接获取容器元素(读写)

4、STL算法的类别

  • 约60个算法
  • ⾮质变的(non-modifying)
    • 不会改变元素内容,如查找、计数等
  • 质变的(modifying)
    • 会改变元素内容,如拷⻉、替换、删除等

5、泛型编程(generic programming)

  • 泛型编程
    • 类型参数化
  • 宏 Macro
  • 函数模板(function template)
  • 类模板(class template)

A、泛型编程

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第3张图片

B、宏 Macro——不太推荐

下面的代码示例定义了 MAX 的宏,当预处理器看到 MAX 的时候会将参数自动替换为 a, b, 需要注意预处理器只会做简单的替换,并不懂C++语法,所以编译器编译的时候可能会出错,

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第4张图片

如下图示例,预处理器只会做简单的替换,

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第5张图片

使用括号,避免出现问题,

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第6张图片

6、C++模板(template)

  • 蓝图(blueprint)
  • 函数和类模板,模板的核心思想就是类型的参数化,这样就可以根据实际需要来替换类型
  • 可以动态替换任何数据类型
  • 编译器会根据蓝图⽣成合适的函数和类
  • 泛型编程(generic programming)/元编程(Meta-programming)
6.1 函数模板(function template)

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第7张图片

将类型泛化成⼀个名称,⽐如:T,当然也可以使用其他合法的标识符

在这里插入图片描述

  • 告诉编译器这是函数模板
  • 同时告诉它 T 是模板参数
  • 这段代码可以通过编译,但不会生成任何代码,只有当调用这个模板时编译器才会生成具体的函数,

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第8张图片

• 此时编译器会根据模板⽣成合适的函数
• 发⽣在编译阶段

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第9张图片

• 编译器可以根据c和d的类型猜出T的类型

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第10张图片

• 适⽤于⼏乎任何类型
这个类型必须⽀持 > 操作符

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第11张图片

• 可以有多个模板参数
• 他们的类型可以不⼀样

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第12张图片

代码:

#include 
#include 

using namespace std;

template <typename T>
T min_func(T a, T b)
{
    return a < b ? a : b;
}

template <class T1, class T2>
void display(T1 a, T2 b)
{
    cout << a << " " << b << endl;
}

int main()
{
    // std::cout << min_func(1, 2) << std::endl;
    // std::cout << min_func(1, 2) << std::endl;
    // std::cout << min_func('B', 'A') << std::endl;
    // std::cout << min_func(3.3, 2.2) << std::endl;
    // std::cout << min_func(5 + 2 * 9, 7 + 2 * 4) << std::endl;

    display<int, int>(1, 2);
    display(20, 30);
    display<char, double>('A', 3.3);
    display("Hello", "World");
    display(2000, string{"Hello"});
    
    return 0;
}
6.2 类模板(class template)
  • 类似函数模板
  • 允许各种类型的替换
  • 编译器会根据蓝图⽣成特定的类
  • vector 和 智能指针也是通过类模板实现的,

A

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第13张图片

B

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第14张图片

C

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第15张图片

D

C++进阶语法——STL 标准模板库(上)(Standard Template Library)【学习笔记(六)】_第16张图片

代码:

#include 
#include 
#include 

using namespace std;

template <typename T>
class Item
{
private:
    std::string name;
    T value;

public:
    Item(std::string name, T value)
        : name{name}, value{value}
    {
    }
    std::string get_name() const { return name; }
    T get_value() const { return value; }
};

template <typename T1, typename T2>
struct My_pair
{
    T1 first;
    T2 second;
};

int main()
{
    // Item item1{"alice", 100};
    // cout << item1.get_name() << " " << item1.get_value() << endl;

    // Item item2{"bob", "C++"};
    // cout << item2.get_name() << " " << item2.get_value() << endl;

    // Item> item3{"carol", {"david", "C++"}};
    // cout << item3.get_name() << " " << item3.get_value().get_name() << " " << item3.get_value().get_value() << endl;

    // vector> vec;
    // vec.push_back(Item("Frank", 100.0));
    // vec.push_back(Item("George", 200.0));
    // vec.push_back(Item("Harry", 300.0));

    // for (const auto &item : vec)
    //     cout << item.get_name() << " " << item.get_value() << endl;

    cout << "=====================" << endl;
    My_pair<std::string, int> p1{"hello", 100};
    My_pair<int, double> p2{200, 3.14};

    cout << p1.first << " " << p1.second << endl;
    cout << p2.first << " " << p2.second << endl;

    return 0;
}

你可能感兴趣的:(C++,c++)