【问题标题】:keeping track of vector elements addresses跟踪向量元素地址
【发布时间】:2013-10-02 14:01:55
【问题描述】:

我想知道是否有办法跟踪向量中元素的地址。

我喜欢使用像std::vector<MyObject> vec 这样的实体元素向量,因为:

  • std::vector 为我完成所有分配/解除分配的工作
  • 它还确保我的元素存储在连续的内存中
  • 我可以从所有使用向量的代码中获益(例如<algorithm>

这正是我想要的。当我想将向量元素的地址/引用存储在其他对象中时,就会出现问题。事实上,当 std::vector 需要重新分配内存时,问题就真的出现了。

我试图找到解决问题的方法:

  • 使用指针向量/智能指针:不,指针将连续分配,但不是元素

  • 使用指针向量/智能指针并为 MyObject 编写我自己的运算符 new/new[]: 嗯,这似乎更好,但没有。通过使用向量来分配我的元素,我可以说:“必须连续分配那些特定的元素集(我在这里不是指std::set),而不是全部”。事实上,由于我想要使用它们的方式,我可能希望拥有其他应该连续分配的元素集,并且使用向量来做到这一点正是(我认为)我需要的。这也意味着我正在做我希望向量做的工作。

  • 为什么不使用boost multi-index? : 在某些方面会做我想做的事,因为我想将我的矢量元素的指针/智能指针存储在其他容器中。但是没有,因为我真的想将我的矢量元素的引用/指针/智能指针存储在其他对象中,而不仅仅是其他容器。

我想要的是一个向量,它可以给我一个指针对象,它总是指向所需元素的地址,我会这样使用它:

std::vector<MyObject> vec;
// insert some elements
...
// get a pointer object by index or by using an iterator
// does something like that exist?
std::vector<MyObject>::pointer ptr = vec.get_pointer_at(5); 

// do what I want on the vector except removing the element
...

// use my pointer whatever reallocations occurred or not
ptr->doSomething();

这听起来像是一个永远不会失效的迭代器,除非我不需要/不想对其执行算术运算(+x、-x、++、--)。

那么,有人可以引导我实现我想要的目标或解释我为什么/在哪里想这样做是错误的吗?如果我错过了一个众所周知的解决方案/或者如果这个问题已经得到解答,请接受我对我缺乏 STL 知识的歉意。

编辑:

我认为,如果我必须编写这种指针,这意味着我想要一些无用的东西,或者我在某个地方错了(除非有人应该已经为此编写了模板)。所以我更希望找到一个经过验证的 C++ 习语来解决这个问题。

【问题讨论】:

  • 如果您需要大量更改向量的内容,则必须更改容器。如果您只更改矢量的内容而不更改大小,那么您应该没问题。
  • 洛朗,你考虑过deque吗?
  • 写一个不失效的迭代器怎么样。将索引存储在迭代器中,而不是元素的地址。
  • @ArtemGr,双端队列不保证将元素存储在连续内存中
  • 我会强烈质疑是否需要存储(即保留)指向vector 中元素的指针。

标签: c++ vector


【解决方案1】:

虽然std::vector 没有给你这样的指针,但你没有理由不能自己做一个。它所需要的只是一个保持对std::vector 对象和索引的引用的类,以及overloads 前缀operator * 和中缀operator -&gt;(您需要四个重载-const 和非const每个运算符)。

你可以这样使用这个指针:

std::vector<int> vect = {2, 4, 6, 8, 10, 12, 14, 16};
vect_ptr<int> ptr(vect, 5); // <<== You need to implement this
*ptr = 123;
cout << *ptr << endl;

这些重载的实现会抓取std::vectorbegin()迭代器,并返回调用vect.at(index)的结果。这看起来像是来自外部的指针,但它指向的对象会随着 std::vector 的内容大小的调整而改变。

【讨论】:

  • 我知道这大致是解决我的问题所需要做的,但我认为好的解决方案必须是使用一些已经存在的成语,如果不是,那么我似乎想要一些无用的东西.
  • @Laurent:我怀疑你想要的是错误的东西。也许如果你告诉我们更多关于你为什么认为你需要这个......
  • 这是我经常遇到的问题:我有对象集合,我喜欢 vector 管理分配过程的方式。我对可以在 stl 容器上执行的操作也很满意。
【解决方案2】:

据我所知,标准库和 Boost 中没有任何内容可以解决您的问题。一种解决方案是实现您自己的元素指针:

template<typename T>
class vector_element
{
public:
    vector_element( std::vector<T>& v, std::size_t i )
      : m_container( v ), m_element_index(i)
    { }

    T& operator*() { return m_container[m_element_index]; }
    T* operator->() { return &m_container[m_element_index]; }
private:
    std::vector<T>& m_container;

    std::size_t m_element_index;
};

【讨论】:

  • 对不起 Julien,但我没有提到元素索引不会变化。事实上,插入会使您的索引值无效,因此您的解决方案不适合
  • 好的,我意识到你们都建议使用索引并避免进行插入(除了 push_back),我会更多地考虑这种解决方案。
猜你喜欢
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 2019-03-07
  • 2020-11-12
  • 2020-11-02
  • 2011-05-15
  • 1970-01-01
  • 2017-09-27
相关资源
最近更新 更多