指向向量元素的c++指针,元素已删除

C++ pointer to vector element, element erased

本文关键字:元素 删除 指针 向量 c++      更新时间:2023-10-16

我希望…

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

问题是:如果从vector中移除元素,指针会发生什么变化?

潜在:

  • 当遍历vector时,是否有任何方法可以检查迭代器是否指向我当前拥有指针的元素?vIterator == pElement会这么做吗?
  • 是否有任何方法从向量中删除元素,只有指向该元素的指针?如果前一个问题的答案是肯定的,那么我想我可以用循环来实现它。

提前感谢!

  1. 它现在将指向无效内存a或指向不同的对象。一般来说,使用指针现在是未定义的行为。
  2. if(&*vIterator == ptr)
        ... 
    

    其中*从迭代器获得对象的引用,&给出它的地址。注意,虽然&*对指针是无操作的,但这里我们需要它,因为迭代器重载了*

  3. 你可以用线性搜索,但这是不必要的低效。您可以利用存储是连续的这一事实,并执行:

    vec.erase(vec.begin()+(ptr-&vec[0]));
    

    ptr-&vec[0]根据通常的指针运算给出了vector中的索引,将其添加到begin迭代器中会得到指向它的迭代器。


。从技术上讲,vector不允许在移除元素时释放内存,所以说它可能指向一个无效(=已经销毁)的对象可能更正确。

指针删除对象

这在很大程度上取决于你如何将类存储在vector中。让我们假设,您正在按照以下方式进行操作:

std::vector<MyClass> classes;

如果您查看std::vector的构造函数,您将看到,它还接受另一个参数,分配器。这是因为vector负责为它保存的项分配和释放内存。

如果使用上述符号,每次向vector中添加元素时,vector都会分配内存,并在移除元素时释放内存。因此,如果你保留了一个指向vector中某个元素的指针并将其移除,那么该指针将指向无效的内存(释放的对象),你不应该再使用它。

如果按照以下方式保存对象,情况就不同了:

std::vector<MyClass *> classes;
在这种情况下,vector只负责保持指针指向类,并分配和释放指针(不考虑它们指向什么)。然后负责创建和销毁指向vector中保存的指针的元素。

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

删除

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

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

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

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()
);

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

以下是std::vector:erase

的文档

删除元素

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

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

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

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

最好的情况是元素被重新定位到现有内存中。即使这样…

如果你有一个指针指向vector的第n个元素,而vector的大小小于n,那么你持有的是一个悬空指针。如果访问指针,可能会得到未定义的行为。如果vector中的元素数大于或等于n,则指向一个新对象,但它仍然是一个有效对象。

Question当遍历vector对象时,是否有办法检查迭代器是否指向当前指针所指向的元素?vIterator == pElement能做到吗?

答案您可以使用:

检查是否有元素的地址

if (myptr == &(*iter))

问题是否有一种方法可以仅使用指向该元素的指针从vector中删除该元素?

答案既然上一题的答案是"是",那么这一题的答案也是"是"。