back_insert_iterator-尾插迭代器类

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容器

  1. redis.smembers("key",it),就是把查到的 key 对应的 value,输出到这个 迭代器对象 绑定的容器当中,内部会执行,***item = 拿到的redis元素,operator++(int) ) = val;**会调用operator=()运算符重载,对 item 对象绑定的container容器进行push_back尾插操作。

但如果绑定的容器,比如set,根本没有对应的push_back()方法,就会报错,比如下面的这行


完,感谢阅读。

相关推荐
DisonTangor1 小时前
MOSS-Image-Base 实战:从文生图到 JSON 布局精准控图
人工智能·ai作画·开源·aigc·1024程序员节
TechVoyager_82461 小时前
十六个调试引脚的两副面孔:IT66322 切换芯片的引脚复用与功耗分档
1024程序员节·切换芯片·引脚复用·功耗分档
lunar_coder1 小时前
【C++】如何解决智能指针的析构函数,如何实现shared_ptr的引用计数以及解决shared_ptr的循环引用
c++·1024程序员节
瑞克-桑切斯1 小时前
脚本陷入自循环的解决方法
1024程序员节
Java开发追求者1 小时前
windows快速安装docker
windows·docker·安装·1024程序员节
我叫洋洋1 小时前
用 Qoder(AI 编程助手)把 Cadence 16.6 从零配到能画板
人工智能·单片机·嵌入式硬件·电路·1024程序员节
ai_coder_ai1 小时前
自动化脚本最佳实践
1024程序员节
坐吃山猪1 小时前
Godot01-初体验
godot·1024程序员节
EnCi Zheng2 小时前
PostgreSQL 实战指南:安装配置、数据类型、索引选型、MVCC 事务与高可用备份全解析
数据库·sql·postgresql·索引·1024程序员节