The following code raises a runtime error:
#include <iostream>
#include <iterator>
#include <ext/slist>
class IntList : public __gnu_cxx::slist<int> {
public:
IntList() { tail_ = begin(); } // seems that there is a problem here
void append(const int node) { tail_ = insert_after(tail_, node); }
private:
iterator tail_;
};
int 开发者_开发技巧main() {
IntList list;
list.append(1);
list.append(2);
list.append(3);
for (IntList::iterator i = list.begin(); i != list.end(); ++i) {
std::cout << *i << " ";
}
return 0;
}
Seems that the problem is in the constructor IntList()
. Is it because it calls the member function begin()
?
Looks like You are inserting after end();
In the body of the constructor
IntList() { tail_ = begin(); }
the base class is constructed and it's members can be called, but for an empty list, it should return end();
The documentation for slist<> indicates that the iterator provided to insert_after must be dereferenceable.
Since your list is empty the begin() returns end() and is thus not dereferenceable.
See documentation here:
http://www.sgi.com/tech/stl/Slist.html
iterator insert_after(iterator pos, const value_type& x)
pos must be a dereferenceable iterator in *this. (That is, pos may not be end().) Inserts a copy of x immediately following pos. The return value is an iterator that points to the new element. Complexity: constant time.
Your problem is not in the constructor but in the first call to append()
. Because your list is empty begin()
equals end()
. end()
is a valid iterator, but the one after that isn't. To solve that particular problem try calling insert()
instead.
That said, a fast peek at <ext/slist>
confirms that the destructor of slist
isn't virtual, which means slist
wasn't intended to be derived from.
.begin() is invalid if there are no elements in your collection.
精彩评论