1.传统迭代器能干啥
比如,
cpp
vector<int> v = {1,2,3};
auto it = v.begin();
*it = 100;
迭代器指向一个确定的元素,通过 *这些来修改这个位置的值
本意是,把原迭代器 src 的值,写到目标迭代器 dest 指向的位置,然后目标迭代器dest移动到下一个位置。
cpp
*dest = *src;
++dest;
但有一个场景,
想把一个vector容器中的值,拷贝到另一个空容器当中,也就是往空容器中追加元素,
cpp
vector<int> src{1,2,3};
vector<int> dst; // 空的!内部指针为nullptr,管理堆上的空间,还没有malloc
copy(src.begin(), src.end(), dst.begin()); // ❌ _start=nullptr,崩溃!
普通迭代器只能修改已经存在的值,不能自动新增元素
2.引入back_inserter_iterator 迭代器
不绑定固定元素,而是直接绑定一个容器,copy的时候,直接container.push_back()元素
遇到赋值 *dst=val,不写原有位置,直接在尾部追加新元素,
cpp
vector<int> src{1,2,3};
vector<int> dst;
copy(src.begin(), src.end(), back_inserter(dst)); // ✅ 完美工作
这样,++是空操作,因为它不存在下一个位置,每次统一追加到末尾
3.看源码具体实现细节
back_inserter是一个函数,拿传入的容器_x,构造一个 back_insert_iterator 对象,返回给我们
cpp
template<typename _Container>
inline back_insert_iterator<_Container> back_inserter(_Container& __x)
{
return back_insert_iterator<_Container>(__x);
}
back_insert_iterator是一个模板类,通过它构造出一个迭代器对象,这个对象内部存了容器的指针,操作这个迭代器对象,最终会修改它绑定的容器。
这个对象的目的不是修改某个已经存在的值,而是为了在尾部push_back追加元素,它永远绑定同一个容器,永远在尾部追加。
cpp
template<typename _Container>
class back_insert_iterator : public iterator<output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;
public:
/// A nested typedef for the type of whatever container you used.
// 默认构造
constexpr back_insert_iterator() noexcept : container(nullptr) { }
// 带参构造
back_insert_iterator(_Container& __x) : container(std::__addressof(__x)) { }
// =运算符重载
//左值引用
//const value_type& --const string&
back_insert_iterator& operator=(const typename _Container::value_type& __value)
{
container->push_back(__value);
return *this;
}
//value_type&& --string&&
// 右值引用,container __value,调用容器的移动 push_back,不拷贝,直接转移资源
back_insert_iterator& operator=(typename _Container::value_type&& __value)
{
container->push_back(std::move(__value));
return *this;
}
// * 和 ++ 全是空壳,只是为了适配 STL 算法统一的写法
/// Simply returns *this. (This %iterator does not @a move.)
back_insert_iterator& operator*()
{ return *this; }
back_insert_iterator& operator++()
{ return *this; }
back_insert_iterator operator++(int)
{ return *this; }
};
4.redis中的使用
cpp
vector<string> res;
auto item = std::back_inserter(res);
redis.smembers("key",item);
1.调用back_inserter函数,返回back_insert_iterateo对象
2.调用back_insert_iterator类的拷贝构造,给这个对象内部容器指针绑定vector容器
- redis.smembers("key",it),就是把查到的 key 对应的 value,输出到这个 迭代器对象 绑定的容器当中,内部会执行,***item = 拿到的redis元素,operator++(int) ) = val;**会调用operator=()运算符重载,对 item 对象绑定的container容器进行push_back尾插操作。
但如果绑定的容器,比如set,根本没有对应的push_back()方法,就会报错,比如下面的这行

完,感谢阅读。