昨天忽然想到,emplace_back和push_back,emplace_back本质就是移动语义吗,然后在容器后边直接构造,只有一次构造,我就想,那push_back一个右值的时候,是不是和emplace_back一模一样的啊,然后翻了翻以前自己的博客(请神上身了属于是),然后直接绷不住了,写的什么玩意,一点不深刻。有一种看自己五年前QQ动态的美(人果然不能共情曾经的自己)。

实际上哈,push_back左值右值是不一样的,会调用重载的不同版本的push_back函数,都要调用构造函数创建对象,区别只在于传入左值调用拷贝构造函数,传入右值调用移动构造函数,而emplace_back是完美转发参数给内部,调用的构造函数。

到此为止。

———————————————————不知道华不华丽的分割线—————————————————

迭代器,用b站宇文新粥的说法,就是给指针穿上了华丽的衣服,是指针的钢铁侠战甲

迭代器,实际上是类or结构体,里面封装了一个对应容器的指针,以及所有相关的操作符重载,目的就是让迭代器有指针的所有功能

为什么要迭代器而不是指针

因为容器是多种多样的,比如vector是内存分布在相邻地址,而list就是链表,每个节点相隔甚远,map什么的用红黑树实现就更别说了,而容器算法很多又是通用的,比如sort(list不能用),find等,为了让list也能用类似原生指针的东西访问,我们采用了迭代器。

不同容器的迭代器是不一样的,比如vector就很类似原生指针,而其他的只是重载函数实现了类似效果

容器与迭代器的关系

  • 每个容器类(如 std::vector, std::list, std::map 等)都在其内部定义了至少一种或多种迭代器类型(例如 iteratorconst_iterator)。这些迭代器类型是该容器的友元类,或者直接定义在容器类内部,以便访问容器的私有成员(如 vector 的底层数组指针,list 的节点指针)。
  • 容器的 begin()end() 成员函数负责创建并返回该容器特定类型的迭代器对象。

迭代器特性 (Iterator Traits)

标准库算法(如 std::sort, std::find)是泛型的,它们通过模板参数接收迭代器。为了知道传入的迭代器具备哪些能力(属于哪个类别),以及它指向的元素类型是什么,标准库使用了一个叫做 std::iterator_traits 的模板元编程技术。

std::iterator_traits<Iterator> 可以提取出迭代器的以下信息:

  • iterator_category: 迭代器类别(如 std::random_access_iterator_tag
  • value_type: 迭代器指向的元素类型
  • difference_type: 两个迭代器之间的距离类型
  • pointer: 指向元素类型的指针类型
  • reference: 元素类型的引用类型

自定义的迭代器需要通过继承 std::iterator 或在迭代器类中定义这些 typedef 来配合 std::iterator_traits

type traits(类型萃取)

主要体现在算法如何根据迭代器的特性来选择最优化的实现路径

核心机制是通过 std::iterator_traits 这个类型萃取模板来实现的。

1. std::iterator_traits 的作用

std::iterator_traits 是一个特殊的类型萃取模板,它的作用是从任何迭代器类型 Iterator 中提取出关于该迭代器的标准信息。这些信息通常是通过迭代器类内部定义的 typedef 来提供的。std::iterator_traits 会查找并暴露这些嵌套类型,使得算法可以通过统一的方式访问它们。

std::iterator_traits<Iterator> 通常会提供以下几个重要的嵌套类型(即萃取出的特性):

  • value_type: 迭代器所指向元素的类型。
  • difference_type: 用于表示两个迭代器之间距离的类型(通常是 ptrdiff_t)。
  • pointer: 迭代器指向元素的指针类型。
  • reference: 迭代器指向元素的引用类型。
  • iterator_category: 这是一个非常重要的特性,它指示了迭代器的能力(例如,输入迭代器、前向迭代器、随机访问迭代器等)。

std::iterator_traits 还为原始指针类型(如 T*)提供了偏特化,使得原始指针也能像 STL 迭代器一样工作,并被识别为随机访问迭代器。

2. 迭代器分类与标签 (Iterator Categories and Tags)

iterator_category 是连接 Type Traits 和迭代器能力的关键。C++ 定义了一系列的标签类型来表示不同的迭代器类别,它们之间存在继承关系:

  • std::input_iterator_tag (输入迭代器)
  • std::output_iterator_tag (输出迭代器)
  • std::forward_iterator_tag (前向迭代器) - 继承自 input_iterator_tagoutput_iterator_tag
  • std::bidirectional_iterator_tag (双向迭代器) - 继承自 forward_iterator_tag
  • std::random_access_iterator_tag (随机访问迭代器) - 继承自 bidirectional_iterator_tag

一个迭代器类型通过在其内部定义 iterator_category 为这些标签类型之一,来声明自己的能力。例如,std::vector 的迭代器内部会定义 typedef std::random_access_iterator_tag iterator_category;

3. 算法如何利用 std::iterator_traits 和分类标签

STL 算法(如 std::advance, std::distance, std::copy, std::sort 等)是模板函数,它们接受迭代器作为参数。在算法的内部实现中,它们会使用 std::iterator_traits 来获取迭代器的特性,尤其是 iterator_category

基于 iterator_category 的不同,算法会采用不同的实现策略。这通常通过标签分派 (Tag Dispatching) 或 C++17 后的 if constexpr 来实现,这是一种编译时多态。