在 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尝试 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++ 中,如何获取指向向量的指针?的主要内容,如果未能解决你的问题,请参考以下文章