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

Posted

技术标签:

【中文标题】在 C++ 中,如何获取指向向量的指针?【英文标题】:In C++, how can I get a pointer into a vector? 【发布时间】:2009-04-14 19:42:11 【问题描述】:

我正在编写一些 C++ 代码来操作一堆大小不断变化并因此不断重新分配的向量。

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

显然,实际指针在重新分配后将无效,我的理解是迭代器在重新分配后也无效。另请注意,我不关心元素是否插入到我的对象之前,因此这些“指针”实际上不需要记住任何东西,只需要一个向量和一个索引。

现在,我自己可以轻松编写这样的课程。有人(Boost?STL?)已经为我做过了吗?

编辑:答案没有解决我的问题。 我问这个功能是否是任何标准库。我认为答案是“否”?

【问题讨论】:

附言。如果这是一个愚蠢/重复的问题,如果有人提供参考,我很乐意将其删除。谢谢! 您有什么理由不能为此使用 std::vector 吗? 显然,因为他不仅要保留向量,还要保留向量中的位置。如果向量从未重新分配,他会想要一个迭代器。想想“vector bar; Myiterator mi(bar, 3);”所以 *mi 永远是 bar[3]。 你需要一个 bool* 到 std::vector 吗?可能会很痛苦 我认为标准库(STL 和 Boost)中没有解决方案。 【参考方案1】:

尝试 std::pair,因为向量的位置和元素的索引都不会改变。 或者,作为一个班级:

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 - 打败我。我建议的唯一改进是使 vectorptr 成为引用而不是指针。 您还需要其他运算符吗? 但请记住使用 size_t 而不是 int! (显然使用正确的模板语法) 您可能希望扩展为具有 RandomAccessIterator 语义 可能不得不为读者留下一些练习。 ;v)【参考方案2】:

An article on persistent iterators,加上implementation。

【讨论】:

【参考方案3】:

总结一些想法。这是一个极简包装器,它试图模仿迭代器,但与向量的迭代器相反,它仍然有效。

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

【讨论】:

【参考方案4】:

不幸的是,一旦您修改了向量,将不再保证“指向”向量元素的迭代器是有效的。我所知道的唯一 STL 结构即使在结构发生变化时也能保持迭代器有效是 list。如果您只想对结构进行顺序迭代,则可以使用 std::list 否则我不知道任何其他可以帮助您的库;这并不意味着没有。

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

【讨论】:

map 和 set 也保留有效的迭代器。【参考方案5】:

使用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;
;

【讨论】:

【参考方案6】:

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

但是我认为整个场景的设计很糟糕,您最好重新设计您的场景,这样您就没有这样的要求了。

【讨论】:

【参考方案7】:

根据您的使用模式,std::deque 可能满足您的要求。仅当您插入或删除不在开头或结尾的项目时,指向双端队列的指针才会失效 - 换句话说, push_front() 和 push_back() 不会使指向双端队列的指针失效,但其他更改会。你得到了与向量基本相同的接口,但当然底层存储是不连续的。

【讨论】:

我觉得很奇怪有人否决了这个答案。 (我赞成平衡。)在我的情况下,我只使用双端队列操作,并且深度指针指向双端队列的属性会很有用,即使它没有直接解决我的问题。所以谢谢!

以上是关于在 C++ 中,如何获取指向向量的指针?的主要内容,如果未能解决你的问题,请参考以下文章

检查指向向量 C++ 中对象的指针

如何从 C++ 中的“指向对象的指针”向量访问对象

我可以直接从 C++ 中向量元素的指针获取索引吗?

如何有效地为现代 C++ 中指向虚拟基类的指针向量分配空间

如何获取在 C++ 中排序后保留的列表元素的指针

指向向量的 C++ 指针