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

发布于 2024-08-18 12:19:26 字数 362 浏览 6 评论 0 原文

好吧,我不知道这是否可能,但问题是:

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

vector<stPiece> pieces;

是否可以从片段中删除“mother”引用的片段,仅以该指针作为引用?如何?

它会与其他参考资料混淆吗? (即,如果它不是向量中的最后一个元素,则通过将下一个元素移动到其他内存位置,而其他“*mothers”保持不变)。当然,我假设所有子块都将被删除(因此我不需要更新任何指向同一个母块的指针)。

谢谢!

Well, I don't know if it is possible, but the thing would be:

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

vector<stPiece> pieces;

Is it possible to erase the piece referenced by 'mother' from pieces, having just that pointer as a reference? How?

Would it mess with the other references? (i.e. if it is not the last element in the vector, by shifting the next elements to other memory positions, while the other '*mothers' remain constant). Of course, I assuming that all the child pieces will be deleted (so I won't need to update any pointer that goes to the same mother).

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

流星番茄 2024-08-25 12:19:26

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

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

要回答您的主要问题:您无法直接删除指针指向的元素,您首先需要在向量中搜索以找到它,或者计算它在向量中的索引。

不将指针存储到 pieces 中作为 mother 而是将元素的索引存储起来会使其更加健壮,这样至少插入新元素不会破坏现有的 母亲的。但从 pieces 中删除仍然会将元素转移到新索引。

使用 std::list 作为 片段并将迭代器存储到其中作为mother可能是一个解决方案。如果删除/添加该列表中的其他元素,std::list 的迭代器不会失效。如果不同的元素可以具有相同的 mother ,那么您仍然无法确定何时删除 mother 元素,而不是使用 boost::shared_ptr 会更简单。

If your mother pointers point directly to elements of the pieces vector you will get in all kinds of trouble.

Deleting an element from pieces will shift all the positions of the elements at higher indexes. Even inserting elements can make all the pointers invalid, since the vector might need to reallocate it's internal array which might transfer all the elements to new positions in memory.

To answer your main question: You can't delete the element you have the pointer to directly, you would first need search through the vector to find it, or calculate it's index in the vector.

Not storing pointers into pieces as mother but instead the indexes of the elements would make it a bit more robust, so that at least inserting new elements could not break the existing mothers. But deleting from pieces would still shift elements to new indexes.

Using a std::list for pieces and storing iterators into that as mother might be a solution. Iterators of std::list are not invalidated if other elements are of that list are removed/added. If different elements can have the same mother you still have a problem finding out when to remove the mother elements, than maybe using boost::shared_ptr would be simpler.

似梦非梦 2024-08-25 12:19:26

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

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。

我不确定我是否理解“假设所有子片段都将被删除”的意思。

It is not exactly clear how the entire data structure is organized and what the consequences are going to be, but it is perfectly possible to erase an element from the vector by having a pointer to that element and the vector itself. You just need to convert the pointer to an iterator first. For example, having a vector

vector<stPiece> pieces; 

and a pointer into that vector

stPiece *mother;

you can convert the pointer to an index

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

then convert the index to an iterator

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

then erase the element

pieces.erase(it);

and that's it.

However, it appears that in your data structure you might have multiple long-lived pointers pointing into the same vector. Any attempts to erase elements from such vector will immediately invalidate all these pointers. It theoretically is possible to "restore" their validity, if you do everything carefully, but this is going to a major PITA.

I'm not sure I understand what you mean by "assuming that all the child pieces will be deleted".

薄荷港 2024-08-25 12:19:26

是的,你可以删除妈妈引用的那篇文章。

如果您删除“mother”引用的块,则其所有子项中的mother 指针将变得悬空,您必须注意这一点。

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

Yes, you can erase the piece referenced by mother.

If you delete the piece referenced by 'mother', the mother pointer in all its children will become dangling, you'll have to take care of this.

About the shifting of elements in the vector, you need not do it, its taken care by the vector class.

浅沫记忆 2024-08-25 12:19:26

简短的回答:不。

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

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

vector<stPiece*> pieces

当向向量添加片段或从向量中删除片段时,母指针不会改变。缺点是:

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

后两点在您的应用程序中可能很重要,也可能不重要。

Short answer: no.

The pieces are stored in the vector by value. A vector iterator is therefore a pointer to a piece. This means, then, that a pointer to the mother piece is the same as the vector's iterator at the mother. Vector iterators are invalidated on insertion (all iterators) and erasure (all iterators past the erased iterator), which means memory locations will change and it will be nearly impossible to keep all the pointers updated.

You could store dynamically allocated pieces in the vector, i.e.:

vector<stPiece*> pieces

The mother pointers won't change as pieces are added/removed to/from the vector. The downsides are:

  • you now have to manage memory (new/delete each piece)
  • it uses more memory per piece (the pointers in pieces)
  • it may be slower because you lose spatial locality (cache efficiency) because it is no longer a contiguous array of stPiece objects

The latter two points may or may not be important in your application.

孤芳又自赏 2024-08-25 12:19:26

您编写的代码是一棵单链接树。您可能不希望一个对象包含所有 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 );
    }
};

关键点是包含某些对象和仅仅能够迭代它们之间是有区别的。如果使用最明显的方式创建和删除对象不使用容器,那么它们可能不应该在其中。

What you have coded is a singly-linked tree. You probably don't want an object to contain all your stPieces, because that would get in the way of implementing creation and deletion semantics.

I'm guessing that you want to delete mother after all the children are gone.

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

The key point is that there's a difference between containing some objects and merely being able to iterate over them. If using the most obvious way to create and delete the objects isn't using the container, they probably shouldn't be in it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文