我正在编写一些C ++代码,用于处理大量变化的向量,因此不断重新分配。
我希望得到这些向量的“指针”,即使在重新分配向量之后仍然有效。更具体地说,我只想要这些“指针”来记住它们指向哪个向量以及它们指向的索引。当我使用标准(* ptr)语法取消引用它们时,我只是希望它们进行明显的查找。
显然,实际指针在重新分配后无效,我的理解是迭代器在重新分配后也无效。另请注意,我不关心元素是否在我的对象之前插入,因此这些“指针”实际上不必记住除了向量和索引之外的任何内容。
现在,我可以轻松地自己写这样的课程。有没有人(Boost?STL?)已经为我完成了它?
修改:答案没有解决我的问题。 我问这个功能是否是任何标准库。我把回复视为“否”?
答案 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)
// 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()不会使指向无效的指针无效,但其他更改会有效。您获得的基本上与向量相同,但当然底层存储不是连续的。