当前位置: 首页 > news >正文

list补充

1.operator->重载函数与operator*重载函数

函数返回的是const T*类型(T 是模板),但是下面却用一个->,则是如何打印出对应的值呢,是因为这里省略了一个->,所以是有俩个的,这样就是把T* 再解引一次,就是val了,*就是直接返回值的引用。

	const T* operator->(){return &_node->_data;}const T& operator*(){return _node->_data;}void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){*it += 10;cout << *it << " ";++it;}cout << endl;for (auto e : lt){cout << e << " ";}cout << endl;print_container(lt);list<AA> lta;lta.push_back(AA());lta.push_back(AA());lta.push_back(AA());lta.push_back(AA());list<AA>::iterator ita = lta.begin();while (ita != lta.end()){//cout << (*ita)._a1 << ":" << (*ita)._a2 << endl;// 特殊处理,本来应该是两个->才合理,为了可读性,省略了一个->cout << ita->_a1 << ":" << ita->_a2 << endl;cout << ita.operator->()->_a1 << ":" << ita.operator->()->_a2 << endl;++ita;}cout << endl;}

2.Container容器

这里是一个容器,可以接受多类型并打印值,如果实参是list<int>,则这里就会先到list去获取对应的迭代器,然后用重载函数*打印值,所以这个函数是可以打印多类型的模板函数。

(若没有按需实例化则细节代码不会检查,只检查明显语法错误)

// 按需实例化// T* const ptr1// const T* ptr2template<class Container>void print_container(const Container& con){// const iterator -> 迭代器本身不能修改// const_iterator -> 指向内容不能修改typename Container::const_iterator it = con.begin();//auto it = con.begin();while (it != con.end()){//*it += 10;cout << *it << " ";++it;}cout << endl;for (auto e : con){cout << e << " ";}cout << endl;}

3.后置++与--

跟前置++与--的区别就是多了一个int的形参,并且后置++和--还需要返回一开始的位置,因为在C的后置++是这行代码结束才++,所以未结束时还是原来的样子。

	Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}

4.析构函数

这先调用clear函数,clear函数会一个一个删除it位置的数据,这里的erase会返回删除位置的下一个位置,所以要更新it的位置需要接受返回值,然后在把堆区上申请的空间释放掉。(没有显式写析构一般也不用写拷贝和赋值 不用深拷贝)

		~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}

5.构造函数

默认构造先申请空间,然后变成哨兵位的形式,带参构造也是先调用empty_init函数搞一个哨兵位出来,然后用尾插函数逐个放进去。

void empty_init()
{_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;
}list()
{empty_init();
}// lt2(lt1)
list(const list<T>& lt)
{empty_init();for (auto& e : lt){push_back(e);}
}

 

 6.赋值重载函数

这里会先进行拷贝构造,list It=It3,然后调用swap,swap里面则是调用算法库的swap,通过交换第一个位置和总大小来把俩个对象进行对换。

void swap(list<T>& lt)
{std::swap(_head, lt._head);std::swap(_size, lt._size);
}// lt1 = lt3
list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}

7.隐式转换构造

第一种可以直接把要构造的参数写里面,因为单参数是可以隐式类型转换,在调用func()时用参数也会是隐式转换,因为func的形参是const list<int>&,所以如果参数是单个则可以直接写参数进去,不用先构造在把构造的作为参数去构造另一个对象。

这里il={10,20,30},auto会自动判断是std::initializer_list<int>类型的,也可以通过typeid().name去看看是什么类型的,nitializer_list 允许使用初始化列表语法创建一组元素。

list(initializer_list<T> il)
{empty_init();for (auto& e : il){push_back(e);}
}void func(const list<int>& lt)
{print_container(lt);
}
void test_list4()
{// 直接构造list<int> lt0({ 1,2,3,4,5,6 });// 隐式类型转换list<int> lt1 = { 1,2,3,4,5,6,7,8 };const list<int>& lt3 = { 1,2,3,4,5,6,7,8 };func(lt0);func({ 1,2,3,4,5,6 });print_container(lt1);//auto il = { 10, 20, 30 };
/*	initializer_list<int> il = { 10, 20, 30 };cout << typeid(il).name() << endl;cout << sizeof(il) << endl;*/
}

 

8.特殊情况增加模板参数减少冗余

把list_iterator的模板参数加俩个,可以把const_iterator和iterator的代码合在一起,在模板list中,给了Ref为T&和const T&,Ptr为T*和const T*,则list中用iterator就是T&和T*,用const_iterator就是const T&和const T*。

template<class T, class Ref, class Ptr>
struct list_iterator
{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node;list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}
};template<class T>class list{typedef list_node<T> Node;public:/*typedef list_iterator<T> iterator;typedef list_const_iterator<T> const_iterator;*/typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;

 

9.总代码

#pragma once
#include<assert.h>namespace bit
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data), _next(nullptr), _prev(nullptr){}};template<class T, class Ref, class Ptr>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node;list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};/*template<class T>struct list_const_iterator{typedef list_node<T> Node;typedef list_const_iterator<T> Self;Node* _node;list_const_iterator(Node* node):_node(node){}const T& operator*(){return _node->_data;}const T* operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};*/template<class T>class list{typedef list_node<T> Node;public:/*typedef list_iterator<T> iterator;typedef list_const_iterator<T> const_iterator;*/typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;iterator begin(){/*	iterator it(_head->_next);return it;*///return iterator(_head->_next);return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}list(initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}// lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}// lt1 = lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}// 16:18继续void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}void push_back(const T& x){/*Node* newnode = new Node(x);Node* tail = _head->_prev;tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;++_size;*/insert(end(), x);}void push_front(const T& x){insert(begin(), x);}iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);// prev newnode curnewnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;++_size;return newnode;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator erase(iterator pos){assert(pos != end());Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;--_size;return next;}size_t size() const{return _size;}bool empty() const{return _size == 0;}private:Node* _head;size_t _size;};struct AA{int _a1 = 1;int _a2 = 1;};// 按需实例化// T* const ptr1// const T* ptr2template<class Container>void print_container(const Container& con){// const iterator -> 迭代器本身不能修改// const_iterator -> 指向内容不能修改typename Container::const_iterator it = con.begin();//auto it = con.begin();while (it != con.end()){//*it += 10;cout << *it << " ";++it;}cout << endl;for (auto e : con){cout << e << " ";}cout << endl;}void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){*it += 10;cout << *it << " ";++it;}cout << endl;for (auto e : lt){cout << e << " ";}cout << endl;print_container(lt);list<AA> lta;lta.push_back(AA());lta.push_back(AA());lta.push_back(AA());lta.push_back(AA());list<AA>::iterator ita = lta.begin();while (ita != lta.end()){//cout << (*ita)._a1 << ":" << (*ita)._a2 << endl;// 特殊处理,本来应该是两个->才合理,为了可读性,省略了一个->cout << ita->_a1 << ":" << ita->_a2 << endl;cout << ita.operator->()->_a1 << ":" << ita.operator->()->_a2 << endl;++ita;}cout << endl;}void test_list2(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);// insert以后迭代器不失效list<int>::iterator it = lt.begin();lt.insert(it, 10);*it += 100;print_container(lt);// erase以后迭代器失效// 删除所有的偶数it = lt.begin();while (it != lt.end()){if (*it % 2 == 0){it = lt.erase(it);}else{++it;}}print_container(lt);}void test_list3(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int> lt2(lt1);print_container(lt1);print_container(lt2);list<int> lt3;lt3.push_back(10);lt3.push_back(20);lt3.push_back(30);lt3.push_back(40);lt1 = lt3;print_container(lt1);print_container(lt3);}void func(const list<int>& lt){print_container(lt);}void test_list4(){// 直接构造list<int> lt0({ 1,2,3,4,5,6 });// 隐式类型转换list<int> lt1 = { 1,2,3,4,5,6,7,8 };const list<int>& lt3 = { 1,2,3,4,5,6,7,8 };func(lt0);func({ 1,2,3,4,5,6 });print_container(lt1);//auto il = { 10, 20, 30 };/*	initializer_list<int> il = { 10, 20, 30 };cout << typeid(il).name() << endl;cout << sizeof(il) << endl;*/}
}


http://www.mrgr.cn/news/59491.html

相关文章:

  • VsCode插件:前端每日一题
  • 前端页面手机端触摸屏操作
  • 关于在vue2中接受后端返回的二进制流并进行本地下载
  • 头歌——人工智能(机器学习 --- 决策树2)
  • 论文笔记(五十)Segmentation-driven 6D Object Pose Estimation
  • Java后端面试题:设计模式篇
  • apply,call,bind手写
  • 质量漫谈一
  • xss-labs靶场第十七关测试报告
  • 照片怎么转换成pdf?盘点6种图片转pdf格式有效方法,直击要点!
  • 【Spring MVC】响应结果和设置
  • linux学习笔记 常用命令记录
  • cookie 简介
  • GEE app:全球油棕,橡胶,其他树木,灌木,裸地,水的可视化界面
  • 基于STM32F103的FreeRTOS系列拓展·内存管理
  • 微信好友智能管理神器:微动RPA,重塑私域流量构建新纪元 批量自动添加好友
  • 说一说QWidget
  • 如何从iconfont中获取字体图标并应用到微信小程序中去?
  • 深入理解 Java 中的抽象类
  • 数组和指针复习
  • 为什么说 zsh 是 shell 中的极品?
  • 地球村上一些可能有助于赚钱的20个思维方式
  • 虚拟机上创建的网站在真机上无法访问的解决办法,以及hosts文件编辑的解决办法
  • 5.15 加载内核映像文件(1)
  • 单目深度估计评价指标及其含义说明
  • 线程同步(互斥锁条件变量)