简体   繁体   English

在C ++中,如何将指针指向向量?

[英]In C++, how can I get a pointer into a vector?

I'm writing some C++ code that manipulates a bunch of vectors that are changing in size and are thus being reallocated constantly. 我正在编写一些C ++代码,这些代码操纵着大小不断变化的矢量,因此不断地对其进行重新分配。

I would like to get a "pointer" into these vectors that remains valid even after reallocation of the vector. 我想在这些向量中使用一个“指针”,即使重新分配向量后该指针也仍然有效。 More specifically, I just want these "pointers" to remember which vector they point into and the index to which they point. 更具体地说,我只希望这些“指针”记住它们指向的向量以及它们指向的索引。 When I dereference them using the standard (*ptr) syntax, I just want them to do the obvious lookup. 当我使用标准(* ptr)语法取消引用它们时,我只希望它们进行明显的查找。

Obviously, actual pointers will not be valid after reallocation, and my understanding is that iterators aren't valid after reallocation either. 显然,实际指针在重新分配后将无效,而我的理解是,迭代器在重新分配后也将无效。 Note also that I don't care if elements are inserted before my objects, so these "pointers" really don't have to remember anything but a vector and an index. 还要注意,我不在乎是否在对象之前插入了元素,因此这些“指针”实际上不必记住向量和索引。

Now, I could easily write such a class myself. 现在,我可以轻松编写自己的此类课程。 Has anyone (Boost? STL?) done it for me already? 已经有人(Boost?STL?)为我完成了吗?

Edit : The answers don't address my question. 编辑 :答案不解决我的问题。 I asked if this functionality is any standard library. 我问这个功能是否是任何标准库。 I take the responses as a "no"? 我将回答视为“否”吗?

Try a std::pair< vector*, int>, as neither the position of the vector nor the index of the element changes. 尝试使用std :: pair <vector *,int>,因为矢量的位置和元素的索引都不会改变。
Or, as a class: 或者,作为一个类:

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];}
};

This is the easiest solution that comes to my mind, as neither the STL nor Boost contains anything to do it easier. 这是我想到的最简单的解决方案,因为STL和Boost都不包含任何使它更容易实现的东西。

To summarize some ideas. 总结一些想法。 Here is the minimalist wrapper that tries to mimic iterators but stay valid as opposite to vector's ones. 这是试图模仿迭代器的极简包装器,但与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;
}

And the iterator itself. 还有迭代器本身。

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_;
};

Using boost::iterator_facade : 使用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;
};

Unfortunately, once you modify the vector, the iterators that would "point" to an element of the vector are no longer guaranteed to be valid. 不幸的是,一旦修改了向量,将不再“指向”向量元素的迭代器是有效的。 The only STL structure that I know of which will keep the iterators valid even as the structure is changing is the list<>. 我知道的唯一STL结构(即使结构更改)也可使迭代器保持有效,即list <>。 If you only want sequential iteration of your structures than you can use std::list<> otherwise I do not know of any other library that can help you; 如果只希望顺序迭代结构,则可以使用std :: list <>,否则我不知道有任何其他库可以为您提供帮助; that doesn't mean there isn't one. 这并不意味着没有一个。

Here's some clear documentation on std::list : http://www.cplusplus.com/reference/stl/list/ 这是std :: list上一些清晰的文档: http : //www.cplusplus.com/reference/stl/list/

Unless you write your own version of vector and smart pointer there is no way that a pointer will be valid after a reallocation. 除非您编写自己的向量指针和智能指针版本,否则指针在重新分配后将不会有效。 If you had your own implementations the smart vector could send notifications to your smart pointers. 如果您有自己的实现,那么智能向量可以将通知发送到您的智能指针。

However I think that the whole scenario is a bad design and you might be better of redesigning your scenario so that you don't have a requirement like that. 但是,我认为整个方案是一个糟糕的设计,您最好重新设计方案,以免您没有这样的要求。

Depending on your use pattern, a std::deque may fufil your requirements. 根据您的使用模式, std :: deque可能会满足您的要求。 Pointers into a deque are only invalidated if you insert or delete items not at the beginning or end - in pother words push_front() and push_back() don't invalidate pointers into the deque, but other changes do. 仅当您插入或删除不在开头或结尾的项时,才使双端队列的指针无效-换句话说,push_front()和push_back()不会使双端队列的指针无效,但其他更改也会使该指针无效。 You get basically the same interface as a vector, but of course the underlying storage is not contiguous. 您可以获得与矢量基本相同的接口,但是当然基础存储不是连续的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM