在C ++中,如何获得指向矢量的指针?

时间:2009-04-14 19:42:12

标签: c++ pointers vector

我正在编写一些C ++代码,用于处理大量变化的向量,因此不断重新分配。

我希望得到这些向量的“指针”,即使在重新分配向量之后仍然有效。更具体地说,我只想要这些“指针”来记住它们指向哪个向量以及它们指向的索引。当我使用标准(* ptr)语法取消引用它们时,我只是希望它们进行明显的查找。

显然,实际指针在重新分配后无效,我的理解是迭代器在重新分配后也无效。另请注意,我不关心元素是否在我的对象之前插入,因此这些“指针”实际上不必记住除了向量和索引之外的任何内容。

现在,我可以轻松地自己写这样的课程。有没有人(Boost?STL?)已经为我完成了它?

修改:答案没有解决我的问题。 我问这个功能是否是任何标准库。我把回复视为“否”?

7 个答案:

答案 0 :(得分:22)

尝试使用std :: pair< vector *,int>,因为矢量的位置和元素的索引都没有变化 或者,作为一个班级:

template<class T> class VectorElementPointer
{
  vector<T>& vectorref;
  typename vector<T>::size_type index;
public:
  VectorElementPointer(vector<T>& vref, typename vector<T>::size_type index):vectorref(vref),index(index){}
  T& operator*() const {return vectorref[index];}
  T* operator->() const {return &vectorref[index];}
};

这是我想到的最简单的解决方案,因为STL和Boost都没有包含任何更容易做到的事情。

答案 1 :(得分:9)

答案 2 :(得分:4)

总结一些想法。这是一个极简主义的包装器,试图模仿迭代器,但保持有效,与vector的相反。

void print(const std::string& i)
{
    std::cout << "<" << i << "> ";
}
int main()
{
    typedef std::vector<std::string> Vector;

    Vector v;
    v.push_back("H");
    v.push_back("E");
    v.push_back("W");
    StrongIterator<Vector> it0(v, 0);
    StrongIterator<Vector> it3(v, v.end());

    std::for_each(it0.it(), it3.it(), print);
    std::cout << std::endl;

    v.push_back("O");
    std::for_each(it0.it(), it3.it(), print);

    std::cout << *it0;
    std::cout << it0->c_str();

    return 0;
}

迭代器本身。

template <typename TVector>
class StrongIterator
{
public:
    typedef typename TVector::iterator iterator;
    typedef typename TVector::size_type size_type;
    typedef typename TVector::value_type value_type;
    StrongIterator(TVector& vector,
                   size_type index):
        vector_(vector),
        index_(index)
    {}
    StrongIterator(TVector& vector,
                   iterator it):
        vector_(vector),
        index_(std::distance(vector.begin(), it))
    {}
    iterator it()
    {
        iterator it = vector_.begin();
        std::advance(it, index_);
        return it;
    }
    value_type& operator*()
    {
        return vector_[index_];
    }
    value_type* operator->()
    {
        return &vector_[index_];
    }
private:
    TVector& vector_;
    size_type index_;
};

答案 3 :(得分:2)

使用boost::iterator_facade

// Warning: Untested, not even compiled
template<class VectorT>
class VectorIndex : 
    public boost::iterator_facade<VectorIndex, typename VectorT::reference, boost::random_access_traversal_tag>
{
public:
    VectorIndex(VectorT& Vec, typename VectorT::size_type Index)
    : m_Vec(Vec), m_Index(Index)
    {
    }

private:
    friend class boost::iterator_core_access;

    void increment()
    {
        ++m_Index;
    }

    void decrement()
    {
        --m_Index;
    } 

    void advance(difference_type N)
    {
        m_Index += N;
    }

    difference_type distance_to(const VectorIndex& Other)
    {
        assert(&this->m_Vec == &Other.m_Vec);
        return Other.m_Index = this->m_Index; 
    }

    bool equal(const VectorIndex& Other)const
    {
        return (this->m_Vec == Other.m_Vec)
            && (this->m_Index == Other.m_Index);
    }

    VectorT::reference dereference() const 
    {
        return m_Vec[m_Index];
    }

    VectorT m_Vec;
    VectorT::size_type m_Index;
};

答案 4 :(得分:1)

不幸的是,一旦修改了向量,将“指向”向量元素的迭代器不再保证有效。我所知道的唯一一个STL结构即使在结构发生变化时也能使迭代器保持有效,它是列表&lt;&gt;。如果你只想要结构的连续迭代,那么你可以使用std :: list&lt;&gt;否则我不知道任何其他可以帮助你的图书馆;这并不意味着没有一个。

这里有一些关于std :: list的明确文档:http://www.cplusplus.com/reference/stl/list/

答案 5 :(得分:0)

除非您编写自己的向量和智能指针版本,否则指针在重新分配后无法生效。如果您有自己的实现,智能矢量可以向您的智能指针发送通知。

但是我认为整个场景设计不好,你可能更好地重新设计场景,这样你就没有这样的要求了。

答案 6 :(得分:0)

根据您的使用模式, std :: deque 可能会满足您的要求。如果您插入或删除不在开头或结尾的项目,则只有无效的指针才会失效 - 在pother中,push_front()和push_back()不会使指向无效的指针无效,但其他更改会有效。您获得的基本上与向量相同,但当然底层存储不是连续的。