C++STL初阶(10):list的简易实现(下)

在上一文中我们完成了链表的多数基本接口,本文主要围绕构造函数进行补充

1. 链表的拷贝

在前文中我们没有手动实现拷贝构造,所以使用的就是编译器自动生成的浅拷贝

先使用一下编译器自动生成的浅拷贝:

我们在打印li2之前给li1加入一个数据:

现在还是完全的浅拷贝,拷贝构造过程中相当于只是将一个_head拷贝给另一个。两个链表有相同的_head。

插入一个会影响另外一个。

并且目前我们还没有实现析构函数,否则析构一个还会让另一个也无法使用。


1.1 clear

传统方法是一个一个释放节点。在实现析构之前我们来实现一个clear

每一个容器都有clear,也就是保留大的框架,但是删除里面的数据。

类比到链表中,就是删除数据节点,留下头结点。

请问这样写正确吗:

++不对,it已经失效了。++

复习:

在vector中,insert和erase都会让迭代器失效;

在list中,insert不会出现迭代器失效并且会返回插入的第一个节点,但是erase还是会迭代器失效的,返回的是被删除元素的下一个元素。

再次修改:

++不对,it已经失效了,再++就加多了++

正确写法:

cpp 复制代码
void clear() {
	//iterator it(_head->_next);
	iterator it = begin();
	while (it != end()) {
		it = erase(it);
	}

1.2 析构

析构直接复用clear

析构和clear的区别就是前者会将大结构也清理干净。


1.3 拷贝构造(拷贝构造必须传引用)

综上所述,我们需要自己实现拷贝构造:

在创建一个全新的链表之后,一个一个的将被拷贝链表的内容全部push_back进去

但是给_head赋值这一段其实就是默认构造,我们希望在一开始就调用这个默认构造中的内容。

直接调用默认构造显然是不可以的,我们将里面的内容独立出来。

为什么要将empty_init单独提取出来?

因为拷贝构造在一开始需要使用默认构造中"建立头结点"的功能。

一般的范围for中,for后面都是(auto e: li)

为了应对T是较大的自定义类型的情况,我们将范围for中也传引用。


2. 赋值运算符的重载

因为我们已经实现好了拷贝构造,所以直接传值传参。


3.initializer_list

在initializer_list参与下实现的花括号构造:

实现和拷贝构造非常相似。

因为initializer_list的逻辑就是从initializer_list一个一个拷贝出来。

​​​​​​​

1、initializer_list不需要传引用传参,其本质就是两个指针,可以直接拷贝,代价不大

2、谨慎使用for循环,建议将auto都写成const auto&


小结

链表部分最重要的就是iterator

VS下的vector和string也没有用原生指针,而是封装过的,里面可能包含有标志等变量(比如erase之后不管是否真的失效都通过标志来表现该迭代器已经失效),但是只要观察早期版本,vector和string就是原生指针或者用原生指针换了个名字。

相关推荐
无名猿11 分钟前
unique_ptr 完全指南:独占所有权与零开销
c++·性能优化·内存管理·标准库·现代c++
笑鸿的学习笔记15 分钟前
C++笔记之大块顺序写
java·c++·笔记
无名猿1 小时前
对象构造与析构顺序全解:声明顺序、继承链与逆序析构
c++·内存管理·调试技巧·现代c++
殷色玫瑰1 小时前
C/C++ 内存管理详解:从内存分布到 new/delete 底层原理
java·linux·c语言·c++
C++ 老炮儿的技术栈2 小时前
不一样的数值交换
数据结构·c++·人工智能·算法·c·csdn开发云
C++ 老炮儿的技术栈2 小时前
main函数之后的调用
c语言·c++·人工智能·qt·mfc·c
知识分享小能手2 小时前
C++ 学习教程,从入门到精通,C++ 友元、异常和其他特性 — 详细知识点(15)
开发语言·c++·学习
ebiobiz3 小时前
极海 APM32 使用 Nimmake 编译指南
c++·python·单片机·嵌入式硬件·mcu
朝朝辞暮i3 小时前
C++ 第 26 课:对象、指针与 ->
java·开发语言·c++
2601_962885723 小时前
如何用 Python 做股价历史分位选股?(筛出处于历史低位的股票)
开发语言·python