before_begin
方法在std::forward_list
的上下文中是如何实现的?
我尝试过这样的事情:
template <class _Tp>
typename forward_list<_Tp>::iterator forward_list<_Tp>::before_begin() NOEXCEPT {
return forward_list_iterator<_Tp>(new forward_list_node<_Tp>(_Tp(), m_pHead));
}
template <class _Tp>
typename forward_list<_Tp>::const_iterator forward_list<_Tp>::before_begin() const NOEXCEPT {
return forward_list_const_iterator<_Tp>(new forward_list_node<_Tp>(_Tp(), m_pHead));
}
我理解的是,在调用before_begin
insert_after
等时应使用emplace_after
方法。因此,我使该方法返回iterator
到指向新节点的点至m_pHead
并具有模板类型_Tp
的默认值。但是,我不确定两件事:
1)当我使用模板时,如何获取默认值? _Tp()
是一个合法的表达式,以获取特定类型的默认值(包括原始类型和用户定义的类型)?
2)由于此方法在iterator
之前返回m_pHead
,如果我使用insert_after
作为第一个参数调用其中一个before_begin
重载方法,那么我不会最终将数据插入列表中,但没有更新m_pHead
?
我insert_after
的四个重载之一的实现如下:
template <class _Tp>
void forward_list<_Tp>::insert_after(const_iterator _position, const _Tp& _value) {
forward_list_node<_Tp>* _node = new forward_list_node<_Tp>(_value, _position.m_pNode->m_pNext);
_position.m_pNode->m_pNext = _node;
}
非常感谢您抽出宝贵时间。 :)
编辑:根据T.C.答案链接中的代码,before_begin
应该像这样实现:
iterator before_begin() { return iterator(&head); }
但是,这就是我begin
的实施方式:
template <class _Tp>
typename forward_list<_Tp>::iterator forward_list<_Tp>::begin() NOEXCEPT {
return forward_list_iterator<_Tp>(m_pHead);
}
我真的不知道上面的before_begin
实现应该如何工作(或者我的insert_after
没有正确写入)。
编辑2:根据我的理解,到目前为止,before_begin
应该返回m_pHead
而begin
应该返回m_pHead->m_pNext
。这实际上并不多感觉,因为begin
应隐含地引用m_pHead
,但我认为这是一种解决方法。
答案 0 :(得分:2)
基本理念是:
struct node_base {
node_base * next;
};
template<class T>
struct node : node_base {
T value;
};
template<class T>
struct forward_list_iter {
forward_list_iter(node_base *pn) : pnode(pn) { }
T& operator*() const { return static_cast<node<T>*>(pnode)->value; }
forward_list_iter& operator++() { pnode = pnode->next; return *this; }
// other stuff
node_base* pnode;
};
template<class T>
struct forward_list {
node_base head;
forward_list_iter<T> before_begin() {
return forward_list_iter<T>(&head);
}
forward_list_iter<T> begin() {
return forward_list_iter<T>(head.next);
}
// other stuff
};
head
节点嵌入forward_list
本身,只是一个node_base
,它只包含指向下一个节点的指针。所有其他节点实际上是node<T>
s,它派生自node_base
并存储类型T
的值。迭代器存储node_base *
,并在取消引用时将其强制转换为node<T> *
。 before_begin()
指向head
; begin()
指向head.next
,这实际上是第一个包含值的节点。