[英]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.