C++ STL笔记

文章详细介绍了C++标准模板库(STL)中的主要组件,包括线性和关联性容器如vector、list、map及其内部结构,以及迭代器的分类和设计原则。此外,还讨论了分配器的作用、泛型编程的概念和OOP的对比,以及算法的实现和仿函数在STL中的应用。适配器部分提到了stack、queue和priority_queue等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ STL笔记

侯捷的视频课程的一些笔记

容器

线性容器

容器结构
vector连续数组
list循环双向链表
forward_list单向链表
deque分段连续结构
stackdeque,为容器的适配器(adapter)
queuedeque,为容器的适配器(adapter)

关联性容器

容器结构
set/multiset红黑树
map/multimap红黑树
unordered_multiset哈希表+链表
unordered_multiset哈希表+链表

分配器

不建议主动使用,只建议使用默认的

分配器
allocator默认分配器

operator new

分配器使用operator newoperator delete管理内存,其底层就是malloc和free

OOP(Object-Oriented Programming)和GP(Generic Programing)

OOP将数据结构和算法放在一起

GP将数据结构和算法分开,两者使用iterator沟通

GP中算法使用iterator确定操作范围,并通过iterator获取容器中元素

泛化, 全特化,偏特化

特化应该是隐式实例化,显式实例化和显式具体化

迭代器iterator

迭代器设计原则

算法使用过程中迭代器需要提供的五个属性

iterator_categotry分类
distance距离
value_type类型
reference引用类型
pointer_type指针类型
template<class T>
struct _List_iterator {
    typedef std::bidirectional_iterator_tag 
                      iterator_category;
    typedef T         value_type;
    typedef T*        pointer;
    typedef T&        reference;
    typedef ptrdiff_t difference_type;
    ...
}

迭代器种类

使用结构体表示

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

STL使用模板加特化的方式针对不同的迭代器实现不同的动作

名称含义对应容器
input_iterator_tag
output_iterator_tag可写(修改)不可读
forward_iterator_tag单向迭代,只能++而不能–forward_list
bidirectional_iterator_tag双向迭代,可以++也可以–list
random_access_iterator_tag随机访问vector, array, deque

traits

iterator traits 用于区分class iterator和non-class iterator

使用特化的方式设定non-class iterator的属性

template<class I>
struct iterator_traits {
    typedef typename I::value_type value_type;
}

/**
 * 针对指针类型
**/
template<class T>
struct iterator_traits<T*> {
    typedef typename T value_type;
    ...
}

template<class T>
struct iterator_traits<const T*> {
    typedef typename T value_type;
    ...
}

除此之外,还有针对int,char,double等基本类型的traits

算法

算法结构

STL中算法和容器分开,使用迭代器进行关联

算法所有的信息智能从迭代器中获取

template<typename Iterator>
Algorithm(Iterator iter1, Iterator iter2) {
    ...
}
template<typename Iterator, typename Cmp>
Algorithm(Iterator iter1, Iterator iter2, Cmp cmp) {
    ...
}

Iterator为迭代器,Cmp为比较函数(仿函数),表示如何对两个迭代器指向的对象进行比较,通常为比较大小

仿函数functor

仿函数为算法服务,作为参数传递给算法

functor种类

算术类

进行基本算数计算

template<class T>
struct plus : public binary_function<T, T, T> {
    T operator()(const T& x, const T&y) const {
        return x + y;
    }
}
...
逻辑运算类

进行逻辑运算

template<class T>
struct logical_and : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const {
        return x &&  y;
    }
}
...
相对关系类

将两者进行比较,大于小于或等于等

template<class T>
struct equal_to : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T&y) const {
        return x == y;
    }
}
...

functor条件

functor需要继承指定的结构体

// 包含一个参数
template<class Arg, class Result>
struct unary_function {
    typedef Arg argument_type;
    typedef Result result_type;
}

// 包含两个参数
template<class Arg1, class Arg2, class Result>
struct binary_function {
    typedef Arg argument_type;
    typedef Arg2 second_argument_type;
    typedef Result result_type;
}

适配器adapter

用于将STL的其他组件进行改造,使其适配需要的功能

容器适配器

种类默认顺序容器可用顺序容器说明
stackdequevector,list,deque基础容器必须提供empty(), size(), back(), push_back(), pop_back()运算
queuedequelist,deque基础容器必须提供empty(), size(), front(), back(), push_back(), pop_front()运算
priority_queuevectorvector,deque基础容器必须提供随机访问功能

在定义容器适配器时,模板参数的第二个参数可以指定所使用发的容器类型是哪个

函数适配器

用于对函数进行包装,可以实现类似于柯里化等操作

使用函数适配器,仿函数得符合STL仿函数的要求,即继承那两个结构体中的一个,若没有继承,则函数适配器会无法匹配仿函数拥有变量类型

bind2nd(已过时)

绑定仿函数的第二个参数(second_argument_typebinary_function类型仿函数中含有该类型)为指定值

// 是否小于40
bind2nd(less<int>(), 40);

本来less<int>()需要传入两个参数,而使用bind2md后将其第二个参数变为40,将该函数变为了只需要一个传入参数的函数

not1

对仿函数结果取反

是否不小于40
not1(bind2nd(less<int>(), 40));
bind

bind可以绑定的对象: 函数,函数对象(仿函数),成员函数,成员变量
绑定成员函数和成员变量时bind第一个参数必须是对应的仿函数对象

使用bind时参数按照(函数,参数1,参数2,…)的顺序,如果需要跳过,可以使用std::placeholder

// 相当于bind2nd(less<int>, 40);
bind(less<int>(), std::placeholder::_1, 40); 

对于应用类型和右值引用类型,可以使用std::ref()std::move()

// 传递的为myClass的引用类型
bind(MyFunctor<MyClass>(), ref(myClass));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值