如果我有一个包含std::list<Foo>
并且具有公共方法begin()
和end()
的类来返回该列表的迭代器,那么如何实现其他方法来将迭代器返回到std::list<Foo*>
,最好不使用boost?
我宁愿不维护指针的并行容器。
修改
我有一个很大的代码库,我想改进。它有一个树状数据结构,其基类有一个返回对象子节点的方法:
class FooBase
{
// ...
virtual bool getChildren(std::vector<FooBase *>& children);
virtual size_t getChildrenCount() const { return 0; };
// ...
}
有一个模板化的类实现了子对象的集合:
template <class T>
class FooCollection: public FooBase
{
public:
typedef typename std::list<T> ContainerType;
typedef typename ContainerType::iterator iterator;
typedef typename ContainerType::const_iterator const_iterator;
private:
ContainerType _items;
public:
// ...
const_iterator begin() const { return itemsM.begin(); };
const_iterator end() const { return itemsM.end(); };
iterator begin() { return itemsM.begin(); };
iterator end() { return itemsM.end(); };
virtual bool getChildren(std::vector<FooBase *>& children)
{
for (iterator it = itemsM.begin(); it != itemsM.end(); ++it)
children.push_back(&(*it));
return (itemsM.size() != 0);
};
// ...
};
代码使用不同FooCollection<>
类提供的迭代器(类已知的位置),以及迭代树时的FooBase::getChildren()
。我以为FooBase::getChildren()
可以用迭代器替换,但也许我错了?
答案 0 :(得分:3)
如何编写如下所示的简单迭代器类并使用它
class myIterator : std::iterator<std::list<Foo>::iterator::iterator_category
, Foo*, std::list<Foo>::iterator::distance_type
, Foo**, Foo*&>
{
public:
myIterator(const std::list<Foo>::iterator& lIt) : it(lIt) {}
myIterator(const myIterator& myIt) : it(myIt.it) {}
myIterator& operator++() {++it;return *this;}
myIterator operator++(int)
{
myIterator copy(*this);
++it;
return copy;
}
myIterator& operator--() {--it;return *this;}
myIterator operator--(int)
{
myIterator copy(*this);
--it;
return copy;
}
bool operator==(const myIterator& rhs) {return it==rhs.it;}
bool operator!=(const myIterator& rhs) {return it!=rhs.it;}
Foo* operator*() {return &(*it);}
private:
std::list<Foo>::iterator it;
};
答案 1 :(得分:2)
std::list<Foo>::iterator
的dereference运算符重载返回对相应Foo
对象的引用。因此,如果您想要Foo
对象std::list<Foo>::iterator
上的it
对象的地址,那么您可以使用&*it
,其类型为Foo*
。
如果您确实需要一个可递增的迭代器而不是指针,那么您可以编写一个迭代器类来存储std::list<Foo>::iterator
成员,比如说it
,在取消引用时返回&*it
。请注意,这样的迭代器类只能满足const迭代器的概念,因为&*it
是一个r值。
答案 2 :(得分:2)
这个结构将有所帮助。它修改迭代器,以便取消引用它返回指针而不是引用:
struct PointerInstead : public list<Foo>::iterator {
PointerInstead(const list<Foo>::iterator &x) : list<Foo>::iterator(x) { }
Foo * operator * () const {
Foo &f = *(*( (list<Foo>::iterator *) (this) ));
return &f;
}
};
以下是其使用示例:
for(PointerInstead i = l.begin(); i != l.end(); i++) {
cout << i->first << '\t' << i->second << endl;
printf("%p\n", (*i));
}
然后你可以编写一个返回类似PointerInstead(this-&gt; begin())的pointerBegin()方法。
答案 3 :(得分:1)
可以创建一个或多个指向Foo
std::list<Foo>
元素指针的容器,但它将不可靠。问题是该列表拥有Foo
个项目(它是一个副本),并且允许在未经批准的情况下更改这些项目的位置。因此,如果您有一个指向列表中第3个元素的指针,则列表可以移动元素,并且您的指针将无效(在您不知情的情况下)。
更好的解决方案是动态分配Foo
项并将智能指针存储在不同的列表中。这允许您按不同的键排序项目。例如,您可以按Foo
中的第一个字段排序 list1 ,并按Foo
中的第3个字段排序另一个列表。
你必须提出自定义排序仿函数,因为默认操作是按智能指针的值排序,这是没人真正想要的。