本篇模擬實(shí)現(xiàn)簡(jiǎn)單的list和一些其他注意的點(diǎn)
迭代器
如下所示是利用拷貝構(gòu)造將一個(gè)鏈表中的數(shù)據(jù)挪動(dòng)到另外一個(gè)鏈表中,構(gòu)造兩個(gè)相同的鏈表
list(const list<T>& lt)
{
emptyinit();
for (auto e : lt)
{
push_back(e);
}
}
void test_list1()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
list<int> l2(lt);
}
lt作為形參,傳引用可以提高傳參的效率,同時(shí)應(yīng)該加上const修飾來保證不會(huì)因?yàn)椴恍⌒男薷牧诵螀?dǎo)致外部的實(shí)參也被修改,這樣的結(jié)果是不應(yīng)該的,因此就要加const把這個(gè)形參變成一個(gè)const對(duì)象
而問題又來了,const對(duì)象要使用的是const迭代器,而前面沒有寫const迭代器,因此這里就引入了const迭代器的實(shí)現(xiàn)
從vector的模擬實(shí)現(xiàn)中,看似似乎只需要在原來的迭代器的基礎(chǔ)上加上一個(gè)const即可,但事實(shí)上:
const
迭代器和普通迭代器是兩種不同的迭代器,不能直接在普通的迭代器后面加const
,原因?
要解決這個(gè)問題,先重新回顧一下vector中const迭代器的定義流程:
對(duì)比vector的迭代器,vector中的迭代器const版本和非const版本直接在非const版本后面加const使它變成const迭代器即可,這樣在調(diào)用的時(shí)候就可以直接進(jìn)行調(diào)用
對(duì)iterator
的定義,const版本就是在指針前面加上const,這樣返回的就是const修飾的指針,因此就可以做到通過該迭代器只讀,不可修改的作用
這里的迭代器本質(zhì)上就是指針在底層進(jìn)行訪問,然后我們定義一個(gè)const指針,使得const指針就不能對(duì)指針指向的內(nèi)容進(jìn)行修改了
下面仿照vector修改的原理修改list
要修改的部分其實(shí)就是下面的代碼:
iterator begin()
{
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
在函數(shù)后加const很簡(jiǎn)單,但是核心是要把返回值也定義為const指針版本,這個(gè)過程要如何實(shí)現(xiàn)?
由于這里是把iterator封裝成了一個(gè)類進(jìn)行的實(shí)現(xiàn),因此需要重新封裝一個(gè)類進(jìn)行實(shí)現(xiàn)
template <class T>
struct __list_iterator
{
typedef list_node<T> Node;
typedef __list_iterator<T> self;
// 成員
Node* _node;
__list_iterator(Node* node)
:_node(node)
{}
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;
}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
bool operator==(const self& pos)
{
return _node == pos._node;
}
bool operator!=(const self& pos)
{
return !(*this == pos);
}
};
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)
{}
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;
}
const T& operator*()
{
return _node->_data;
}
const T* operator->()
{
return &_node->_data;
}
bool operator==(const self& pos)
{
return _node == pos._node;
}
bool operator!=(const self& pos)
{
return !(*this == pos);
}
};
但事實(shí)上,這兩份代碼只有很少的地方有區(qū)別,更多的內(nèi)容都是相同的,這樣是不滿足較好的代碼風(fēng)格,因此在stl源碼中,使用了模板對(duì)這兩個(gè)類進(jìn)行了封裝
改進(jìn)版本如下:文章來源:http://www.zghlxwxcb.cn/news/detail-649281.html
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)
{}
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;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator==(const self& pos)
{
return _node == pos._node;
}
bool operator!=(const self& pos)
{
return !(*this == pos);
}
};
template <class T>
class list
{
void emptyinit()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
public:
typedef list_node<T> Node;
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
// 構(gòu)造函數(shù)
list()
{
emptyinit();
}
// 拷貝構(gòu)造
list(const list<T>& lt)
{
emptyinit();
auto it = lt.begin();
//*it = 30;
}
void push_back(const T& x)
{
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
// head tail->prev tail
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
iterator begin()
{
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
const_iterator begin() const
{
return const_iterator(_head->_next);
}
const_iterator end() const
{
return const_iterator(_head);
}
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(x);
// newnode
// prev cur
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return iterator(newnode);
}
iterator erase(iterator pos)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
// prev cur next
prev->_next = cur->_next;
next->_prev = cur->_prev;
return iterator(next);
}
private:
Node* _head;
size_t _size;
};
這里引入了類模板的概念,簡(jiǎn)單來說,當(dāng)需要調(diào)用const類型時(shí)就會(huì)模板實(shí)例化出一個(gè)const版本的迭代器,再進(jìn)行相關(guān)的操作,這樣的操作可以避免代碼冗余,也是模板的強(qiáng)大之處文章來源地址http://www.zghlxwxcb.cn/news/detail-649281.html
模擬實(shí)現(xiàn)
#pragma once
// 實(shí)現(xiàn)的是雙向循環(huán)鏈表,鏈表中應(yīng)該包含節(jié)點(diǎn)類和迭代器類,節(jié)點(diǎn)類用于從內(nèi)存中申請(qǐng)節(jié)點(diǎn),迭代器類用于獲取節(jié)點(diǎn)指針
namespace mylist
{
// 把節(jié)點(diǎn)進(jìn)行封裝,可以動(dòng)態(tài)獲取一個(gè)節(jié)點(diǎn)
template <class T>
struct list_node
{
// 成員
list_node<T>* _next;
list_node<T>* _prev;
T _data;
// 成員函數(shù)
list_node(const T& val = T())
:_data(val)
, _next(nullptr)
, _prev(nullptr)
{}
};
// 對(duì)迭代器進(jìn)行封裝,使得外界看到的是迭代器
// 迭代器當(dāng)中存儲(chǔ)的是某個(gè)節(jié)點(diǎn)的指針
// 可以對(duì)迭代器進(jìn)行各項(xiàng)操作
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)
{}
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;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator==(const self& pos)
{
return _node == pos._node;
}
bool operator!=(const self& pos)
{
return !(*this == pos);
}
};
// 適配器 -- 復(fù)用
template <class T, class Ref, class Ptr >
struct __reverse_iterator
{
typedef list_node<T> Node;
typedef __reverse_iterator<T, Ref, Ptr> self;
// 成員
Node* _node;
__reverse_iterator(Node* node)
:_node(node)
{}
self& operator++()
{
_node = _node->_prev;
return *this;
}
self& operator--()
{
_node = _node->_next;
return *this;
}
self operator++(int)
{
self tmp(*this);
_node = _node->_prev;
return tmp;
}
self operator--(int)
{
self tmp(*this);
_node = _node->_next;
return tmp;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator==(const self& pos)
{
return _node == pos._node;
}
bool operator!=(const self& pos)
{
return !(*this == pos);
}
};
template <class T>
class list
{
void emptyinit()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
public:
typedef list_node<T> Node;
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
typedef __reverse_iterator<T, T&, T*> reverse_iterator;
typedef __reverse_iterator<T, const T&, const T*> const_reverse_iterator;
// 構(gòu)造函數(shù)
list()
{
emptyinit();
}
// 拷貝構(gòu)造
list(const list<T>& lt)
{
emptyinit();
auto it = lt.begin();
//*it = 30;
}
void push_back(const T& x)
{
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
// head tail->prev tail
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
iterator begin()
{
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
const_iterator begin() const
{
return const_iterator(_head->_next);
}
const_iterator end() const
{
return const_iterator(_head);
}
reverse_iterator rbegin()
{
return reverse_iterator(_head->_prev);
}
reverse_iterator rend()
{
return reverse_iterator(_head);
}
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(_head->_prev);
}
const_reverse_iterator rend() const
{
return const_reverse_iterator(_head);
}
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(x);
// newnode
// prev cur
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return iterator(newnode);
}
iterator erase(iterator pos)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
// prev cur next
prev->_next = cur->_next;
next->_prev = cur->_prev;
return iterator(next);
}
private:
Node* _head;
size_t _size;
};
void test_list1()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
cout << "正序" << endl;
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
cout << "逆序" << endl;
auto rit = lt.rbegin();
while (rit != lt.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
}
}
到了這里,關(guān)于C++:模擬實(shí)現(xiàn)list及迭代器類模板優(yōu)化方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!