C ++ - 删除指针引用的向量元素

时间:2010-01-14 04:52:29

标签: c++ pointers vector erase

好吧,我不知道是否有可能,但事情就是:

struct stPiece
{
  /* some stuff */
  stPiece *mother; // pointer to the piece that created this one
};

vector<stPiece> pieces;

是否可以将“母亲”引用的作品从片段中删除,仅将该指针作为参考?怎么样?

是否会混淆其他参考文献? (即如果它不是向量中的最后一个元素,则通过将下一个元素移动到其他存储位置,而另一个'*母亲'保持不变)。当然,我假设所有子片段都将被删除(因此我不需要更新任何指向同一母亲的指针)。

谢谢!

5 个答案:

答案 0 :(得分:2)

如果您的mother指针直接指向pieces向量的元素,您将遇到各种麻烦。

pieces删除元素会将元素的所有位置移位到更高的索引。即使插入元素也会使所有指针无效,因为向量可能需要重新分配它的内部数组,这可能会将所有元素转移到内存中的新位置。

回答你的主要问题:你不能直接删除指针所在的元素,首先需要通过向量搜索来找到它,或者在向量中计算它的索引。

不将指针存储到pieces作为mother,而是元素的索引会使其更加健壮,因此至少插入新元素不会破坏现有的mother秒。但是从pieces删除仍会将元素转移到新索引。

pieces使用std::list并将迭代器存储为mother可能是一种解决方案。如果删除/添加该列表中的其他元素,则std::list的迭代器不会失效。如果不同的元素可以具有相同的mother,那么在查找何时删除mother元素时仍然存在问题,那么使用boost::shared_ptr可能会更简单。

答案 1 :(得分:2)

目前尚不清楚整个数据结构是如何组织的以及结果会是什么,但是通过指向该元素和向量本身来完全可以从向量中删除元素。您只需要首先将指针转换为迭代器。例如,有一个向量

vector<stPiece> pieces; 

和指向该向量的指针

stPiece *mother;

您可以将指针转换为索引

vector<stPiece>::size_type i = mother - &pieces[0];
assert(i < pieces.size());

然后将索引转换为迭代器

vector<stPiece>::iterator it = pieces.begin() + i;

然后删除元素

pieces.erase(it);

就是这样。

但是,在您的数据结构中,您可能会有多个长寿命指针指向同一个向量。任何从这种向量中擦除元素的尝试都会立即使所有这些指针无效。如果你仔细地做所有事情,理论上可以“恢复”它们的有效性,但这将是一个主要的PITA。

我不确定我明白你的意思是“假设所有儿童作品都将被删除”。

答案 2 :(得分:1)

是的,您可以删除母亲引用的作品。

如果删除“母亲”引用的作品,其所有孩子中的母指针将变为悬空,你必须要处理这个问题。< / p>

关于向量中元素的移位,你不需要这样做,它由向量类处理。

答案 3 :(得分:1)

简答:不。

这些碎片按值存储在矢量中。因此,向量迭代器是指向一块的指针。这意味着,指向母件的指针与母亲的矢量迭代器相同。插入(所有迭代器)和擦除(所有迭代器都超过擦除的迭代器)后,矢量迭代器无效,这意味着内存位置将发生变化,几乎不可能保持更新所有指针。

您可以在向量中存储动态分配的部分,即:

vector<stPiece*> pieces

随着向量/从向量中添加/移除片段,母指针不会改变。缺点是:

  • 你现在必须管理记忆(新/删除每件)
  • 它每片使用更多内存(指针分片)
  • 它可能会更慢,因为它失去了空间局部性(缓存效率),因为它不再是stPiece对象的连续数组

后两点在您的申请中可能重要,也可能不重要。

答案 4 :(得分:1)

您编码的是单链树。您可能不希望对象包含所有stPiece,因为这会妨碍实现创建和删除语义。

我猜你想在所有孩子都离开之后删除mother

set< stPiece * > all_pieces;

struct stPiece {
    boost::shared_ptr< stPiece > const mother;
    stPiece( boost::shared_ptr< stPiece > &in_mother )
     : mother( in_mother ) {
        all_pieces.insert( this );
    }
    ~stPiece() {
        all_pieces.erase( this );
    }
};

关键是包含一些对象和仅仅能够迭代它们之间存在差异。如果使用最明显的方法创建和删除对象不使用容器,它们可能不应该在其中。

相关问题