我想要提供的东西:
std::list head;
std::list::node node;
while (node = head->next) {
do something with this node
};
对我而言,列表没有下一个指针是相当奇怪的。
答案 0 :(得分:4)
由于C ++ 11 stl只有一个链表。它的用法类似于普通的双链表。
特别是:
std::forward_list<node> my_list;
for(auto iter = my_list.begin(); iter != my_list.end(); ++iter)
{
node &curr_node = *iter;
// Do something with curr_node.
}
答案 1 :(得分:4)
确实。只有界面发生变化。
std::list
就像您的链接列表一样存储该项目。如果您查找GCC 4.6.1标准库源代码文件std_list.h
,您会发现:
struct _List_node_base
{
_List_node_base* _M_next;
_List_node_base* _M_prev;
//...
};
双重链表。
std::list<T>::iterator
让您以与使用“下一个”指针相同的方式浏览所有元素。同一个文件第151行显示:
_Self&
operator++()
{
_M_node = _M_node->_M_next;
return *this;
}
为程序员隐藏所有实现细节的原因之一是它可以让您轻松更改容器。如果出于性能原因,您想要使用其他容器或自己制作容器,则只需更改类型即可。
typedef std::list<MyItems> itemContainer;
for (itemContainer::const_iterator it = allItems.begin(); it != allItems.end(); ++it)
{
// do something
}
答案 2 :(得分:3)
隐藏了列表的实际实现。由于标准要求在给定位置插入和擦除元素应该可以在恒定时间内我们可以假设将使用类似节点的东西:
23.3.5班级模板列表[列表]
23.3.5.1班级模板列表概述[list.overview]
list
是一个序列容器,它支持双向迭代器,并允许在序列中的任何位置进行常量时间插入和擦除操作,并自动处理存储管理。与向量(23.3.6)和deques(23.3.3)不同,不支持对列表元素的快速随机访问,但许多算法无论如何都只需要顺序访问。
然而,关于C ++容器的重要之处在于它们都提供了相同的接口来实际遍历内容:迭代器:
for(std::list<double>::iterator it = list.begin(); it != list.end(); ++it){
*it += 3.0; // add 3.0 to each element
}
如果您将列表视为带有
的C风格对象struct node{
struct node * next;
struct node * prev;
double value;
};
struct list{
struct node * first;
struct node * last;
}
上面的循环有点等同于
for(struct node * it = list.first; it != list.last + 1; it = it->next){
*it += 3.0; // add 3.0 to each element
}
但是it = it->next
之类的内容隐藏在std::list::iterator
的实际实现中。由于它们为所有类提供了几乎*统一的界面,因此您应该学会使用它们。
*有些确实提供了比其他功能更多的功能,例如RandomAccessIterators
与BidirectionalIterators
,但这是您稍后会学到的。