C++ 如何最有效地迭代私有成员std::vector?

C++ 如何最有效地迭代私有成员std::vector?,c++,for-loop,stl,indexing,iterator,C++,For Loop,Stl,Indexing,Iterator,我正在编写一个实现双链接树的类,我希望用户能够尽可能高效地迭代节点的所有子节点 Tree.h(缩写): 我遗漏了迭代中未涉及的所有内容 class Tree { public: static Tree& root(){ return *root_; } //index-based iteration inline unsigned int numChildren() const{ return childrenSize_; } Tree& getC

我正在编写一个实现双链接树的类,我希望用户能够尽可能高效地迭代节点的所有子节点

Tree.h(缩写): 我遗漏了迭代中未涉及的所有内容

class Tree
{
public:
    static Tree& root(){ return *root_; }
    //index-based iteration
    inline unsigned int numChildren() const{ return childrenSize_; }
    Tree& getChild(unsigned int index) const;                       

    //iterator-based iteration                          
    vector<unique_ptr<Tree>>::iterator children_begin(){
        return children_.begin();
    }
    vector<unique_ptr<Tree>>::iterator children_end(){
        return children_.end();
    }

private:
    vector<unique_ptr<Tree>> children_;
    unsigned int childrenSize_;
    Tree* parent_;

    static unique_ptr<Tree> root_;
};
这看起来既危险又丑陋,但我可以想象它会更快。我这里的问题是,用户只需将unique_ptr移动到其他地方,我希望尽可能限制使用,以避免错误使用该结构

更有效的方法是什么?它到底有多大区别


PS:这是我在撰写本文时提出的第三种方法,但我现在知道了如何实现它:

3.for
(:)
-循环 语法方面,它看起来非常简单,但我不知道(:)-循环的
在内部真正做了什么(可能与迭代器一起工作,如果没有树上的
->begin()
->end()
函数,就无法工作)


额外问题:有可能在我自己的类中实现这个模式吗?

正如@WojitekSurowka所建议的,我研究了这个模式,它似乎是一个很好的选择。然而,它似乎不能与VS2013一起很好地工作,所以我不得不自己编写一个迭代器,这并不像我最初想象的那么难

根据@JoachimPileborg发布的消息,这使我能够使用(:)
-循环的
。但是,请注意,我的解决方案使用了一个完全自定义的迭代器,它不是从任何STL向量派生的,因此不能保证正确处理所有STL操作

Tree.h:
太棒了

有关基于范围的For循环,请参见例如。它还显示了一个等效的实现。我认为,使用它是首选的替代方法。“…开销不大,因为每当树被修改时,子向量的长度都会保存到一个变量中(请相信我),并且获取此长度的函数是内联的。”-抱歉,不能相信你<代码>矢量
记录其当前大小并支持O(1)内联查询。。。重复会降低性能。更一般地说,Joachim的权利——只需提供
begin()
end()
,人们就可以使用范围来表示;如果需要,迭代器可以隐藏
唯一\u ptr
。也可以很容易地支持@JoachimPileborg这个参考资料只表明我的想法行不通,因为
儿童
是私有的(应该保持这种方式),我会再次向用户公开
独特的ptr
,这并不是真正的想法。糟糕。@TonyD我该如何实现
begin()
end()
函数?你能给我指出它的来源吗?@ifrelicht:“引用仅显示…”-只需将
vector::iterator children\u begin()
重命名为
begin()
children\u end()
为一种简单的方法,或者编写自己的
迭代器
类以实现更好的封装-它应该存储一个
向量::迭代器
,并且解引用生成
树&
,而不是
唯一的\u ptr
Tree& myTree = Tree::root();
for(int i = 0; i < myTree.numChildren(); ++i;){
    Tree& child = myTree.getChild(i);
    //do stuff with child
}
Tree& myTree = Tree::root();
for(vector<unique_ptr<Tree>>:iterator it = myTree.children_begin(); it < myTree.children_end(); ++it; ){
    Tree& child = (*(*it));
    //do stuff with child
}
for (Tree& child : Tree::root()){
    //do stuff with child
}
class Tree;

class TreeIterator
{
public:
    TreeIterator(std::vector<unique_ptr<Tree>>::iterator& pos) :
    pos_(pos)
    {};

    bool operator==(const TreeIterator& rhs) { return pos_ == rhs.pos_; }
    bool operator!=(const TreeIterator& rhs) { return pos_ != rhs.pos_; }
    bool operator<=(const TreeIterator& rhs) { return pos_ <= rhs.pos_; }
    bool operator>=(const TreeIterator& rhs) { return pos_ >= rhs.pos_; }
    bool operator<(const TreeIterator& rhs) { return pos_ < rhs.pos_; }
    bool operator>(const TreeIterator& rhs) { return pos_ > rhs.pos_; }

    void operator ++(){ ++pos_; }

    //this is the most important thing!!!
    Tree& operator*(){
        return **pos_; //double-dereferencing
    }

private:
    std::vector<unique_ptr<Tree>>::iterator pos_;
};


class Tree
{
public:
    static Tree& root(){ return *root_; }                   

    //regular begin and end functions for iterators, used by the `for( : )`-loop        
    TreeIterator& begin(){
        return *(beginIter_ = std::move(unique_ptr<TreeIterator>(new TreeIterator(children_.begin()))));
    }
    TreeIterator& begin(){
        return *(endIter_ = std::move(unique_ptr<TreeIterator>(new TreeIterator(children_.end()))));
    }

private:
    vector<unique_ptr<Tree>> children_;
    Tree* parent_;
    unique_ptr<TreeIterator> beginIter_;
    unique_ptr<TreeIterator> endIter_;
    static unique_ptr<Tree> root_;
};
for(Tree& child : Tree::root()){
    //do stuff with child
}