C ++指向矢量元素的指针,元素被擦除

时间:2014-05-16 05:57:02

标签: c++ pointers vector

简单的问题我希望......

我有一个元素向量。元素属于我自己的类类型。我维护一个指向该向量的特定成员的指针。

问题是:如果我从向量中删除元素,指针会发生什么?

子问题

  • 当迭代向量时,有什么方法可以检查迭代器是否指向我当前有指针的元素? vIterator == pElement会这样做吗?
  • 有没有办法从矢量中删除元素,只有指向该元素的指针?如果上一个问题的答案是肯定的,那么我想我可以用循环来做到这一点。

提前致谢!

4 个答案:

答案 0 :(得分:3)

  1. 现在指向无效的内存 a 或其他对象。通常,使用该指针现在是未定义的行为。
  2. if(&*vIterator == ptr)
        ... 
    

    *从迭代器获取对象的引用,&为您提供地址。请注意,尽管&*是指针上的无操作,但我们需要它,因为迭代器会重载*

  3. 您可以使用线性搜索,但它不必要地效率低下。您可以利用存储是连续的这一事实,并且:

    vec.erase(vec.begin()+(ptr-&vec[0]));
    
    由于通常的指针算法,

    ptr-&vec[0]为你提供了向量中的索引,并将它添加到begin迭代器会产生一个迭代器。


  4. 一个。从技术上讲,矢量不允许在元素移除时释放内存,因此可能更正确地说它可能指向无效(=已经被破坏)的对象。

答案 1 :(得分:1)

指向已删除对象的指针

这在很大程度上取决于你如何将类存储在向量中。我们假设您正在以下列方式进行此操作:

std::vector<MyClass> classes;

如果查看std::vector的构造函数,您会看到它还需要另一个参数,即分配器。这是因为vector负责处理项目的内存分配和释放。

如果您使用上述表示法,则向量会在每次向其添加项目时分配内存并在您删除时释放。因此,如果您保持指向向量中某个元素的指针并将其删除,那么指针将指向无效的内存(对于已解除分配的对象),您不应再使用它了。

情况发生变化,如果您按以下方式保留对象:

std::vector<MyClass *> classes;

在这种情况下,vector只负责将指针保存到类中,并将分配和释放指针(不考虑它们指向的是什么)。然后,您负责创建和销毁指向保存在向量中的指针的元素。

<强>迭代

有一种简单的方法可以检查迭代器是否指向特定对象。首先,取消引用迭代器以获取实际对象:(*iter)然后询问该对象的地址:&(*iter)并检查,如果它与对象匹配,则指向该对象。

<强>擦除

是的,你可以 - 例如,简单地使用循环。如果您将实际对象保留在向量中(我提到的第一个选项),Matteo建议的选项将起作用。这是因为vector应该将所有数据保存在连续的内存块中,当你有一个指向它的指针(指针算术)时,很容易评估对象的索引。

答案 2 :(得分:1)

您的矢量拥有对象,但您也希望能够使用指针删除它们。如果将它们直接存储在向量中,则无法清楚地实现此目的,因为您怀疑向量可能会在更改向量时进行重新分配,并且向量中间的插入或删除将使所有指针无效这指向下一个元素。

这是std :: unique_ptr发挥作用的地方。通过在向量中保留智能指针,您仍然可以保留所有权而无需处理内存管理,并且失效不是问题:

std::vector<std::unique_ptr<CustomClass>> objects;
std::unique_ptr<CustomClass> object(new CustomClass());
objects.push_back(std::move(object));

现在假设object_pointer具有您的一个对象的地址,您可以删除该对象而不必担心失效:

objects.erase(
     std::remove_if(objects.begin(), m_objects.end(),
        [&](const std::unique_ptr<CustomClass>& ptr) { return ptr.get() == object_pointer; }),
     objects.end()
);

答案 3 :(得分:0)

问题如果我从向量中删除元素,指针会发生什么?

<强>答案

这是std::vector:erase

上的文档
  

删除元素

     

vector移除单个元素(position)或一系列元素([first,last))。

     

这有效地减少了容器大小,删除了被删除的元素数量。

     

因为vector使用数组作为其底层存储,所以擦除向量末端以外的位置中的元素会导致容器在段擦除后将所有元素重新定位到新位置。与通过其他类型的序列容器(例如listforward_list)对相同操作执行的操作相比,这通常是低效的操作。

我不清楚是否需要将元素重新定位到现有内存,或者编译器可以自由地为元素分配新内存并将元素重定位到新内存,然后删除旧内存

最佳情况是元素被重定位到现有内存。即便如此......

如果在删除元素之前有一个指向vector的第n个元素的指针,并且在删除元素后vector的大小小于n ,你正在坚持一个悬垂的指针。如果访问指针,则可能会出现未定义的行为。如果vector中的元素数量大于或等于n,则表示您指向一个新对象,但它仍然是一个有效对象。

问题当迭代向量时,有什么方法可以检查迭代器是否指向我当前有指针的元素? vIterator == pElement会这样做吗?

回答您可以使用以下方法检查您是否拥有元素的地址:

if(myptr ==&amp;(* iter))

问题有没有办法从矢量中删除元素,只有指向该元素的指针?

回答由于上一个问题的回答是&#34;是&#34;,这个问题的答案也是&#34;是&#34;。