我的 vector::erase 有什么问题吗?
我的程序中有两个向量active
和non_active
。这是指它包含的对象,无论它们是否正在使用。
我有一些代码循环 active
向量并检查任何可能已变为非活动状态的对象。我将它们添加到循环内的 temp_list
中。
然后在循环之后,我使用我的temp_list
并对temp_list
中的所有元素执行non_active.insert
。
之后,我对 active
向量调用 erase
并将其传递给 temp_list
进行擦除。
然而,由于某种原因,erase
崩溃了。
这是代码:
non_active.insert(non_active.begin(), temp_list.begin(), temp_list.end());
active.erase(temp_list.begin(), temp_list.end());
我得到这样的断言:
Expression:("_Pvector == NULL || (((_Myvec*)_Pvector)->_Myfirst <= _Ptr && _Ptr <= ((_Myvect*)_Pvector)->_Mylast)",0)
我在网上查看并看到有一个擦除删除习惯用法,但不确定如何将其应用于从 vector
我没有使用 C++11。
I have two vector<T>
in my program, called active
and non_active
respectively. This refers to the objects it contains, as to whether they are in use or not.
I have some code that loops the active
vector and checks for any objects that might have gone non active. I add these to a temp_list
inside the loop.
Then after the loop, I take my temp_list
and do non_active.insert
of all elements in the temp_list
.
After that, I do call erase
on my active
vector and pass it the temp_list
to erase.
For some reason, however, the erase
crashes.
This is the code:
non_active.insert(non_active.begin(), temp_list.begin(), temp_list.end());
active.erase(temp_list.begin(), temp_list.end());
I get this assertion:
Expression:("_Pvector == NULL || (((_Myvec*)_Pvector)->_Myfirst <= _Ptr && _Ptr <= ((_Myvect*)_Pvector)->_Mylast)",0)
I've looked online and seen that there is a erase-remove idiom, however not sure how I'd apply that to a removing a range of elements from a vector<T>
I'm not using C++11.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
erase
需要传递给它的位于当前向量内的一系列迭代器。您不能将从不同向量获得的迭代器传递给erase
。这是 lambda 支持的可能但效率低下的 C++11 解决方案:
这是不带 lambda 的等效 C++03 解决方案:
如果将
temp_list
替换为std:: set
和带有find
成员函数调用 set 的std::find_if
,性能应该是可以接受的。erase
expects a range of iterators passed to it that lie within the current vector. You cannot pass iterators obtained from a different vector toerase
.Here is a possible, but inefficient, C++11 solution supported by lambdas:
And here is the equivalent C++03 solution without the lambda:
If you replace
temp_list
with astd::set
and thestd::find_if
with afind
member function call on the set, the performance should be acceptable.擦除方法旨在接受同一容器对象的迭代器。您试图将迭代器传递给 temp_list 以用于从活动中删除元素,但出于充分的原因,这是不允许的,因为序列的范围擦除方法旨在指定要删除的序列中的范围。迭代器按该顺序排列很重要,否则我们将指定要擦除的值范围,而不是同一容器内的范围,这是一种成本更高的操作。
您尝试执行的逻辑类型向我表明,一组或列表可能更适合该目的。也就是说,您尝试从容器中间删除匹配特定条件的各种元素并将它们转移到另一个容器,并且您可以通过这种方式消除对 temp_list 的需要。
例如,对于列表,它可能像这样简单:
但是,有时向量可以胜过这些解决方案,并且也许您出于其他原因需要向量(例如确保连续内存)。在这种情况下, std::remove_if 是您最好的选择。
示例:
有关此内容的更多信息可以在“擦除删除习惯用法”主题下找到,并且您可能需要谓词函数对象,具体取决于确定对象是否不再处于活动状态所需的外部状态。
The erase method is intended to accept iterators to the same container object. You're trying to pass in iterators to temp_list to use to erase elements from active which is not allowed for good reasons, as a Sequence's range erase method is intended to specify a range in that Sequence to remove. It's important that the iterators are in that sequence because otherwise we're specifying a range of values to erase rather than a range within the same container which is a much more costly operation.
The type of logic you're trying to perform suggests to me that a set or list might be better suited for the purpose. That is, you're trying to erase various elements from the middle of a container that match a certain condition and transfer them to another container, and you could eliminate the need for temp_list this way.
With list, for example, it could be as easy as this:
However, sometimes vector can outperform these solutions, and maybe you have need for vector for other reasons (like ensuring contiguous memory). In that case, std::remove_if is your best bet.
Example:
More info on this can be found under the topic, 'erase-remove idiom' and you may need predicate function objects depending on what external states are required to determine if an object is no longer active.
实际上,您可以使擦除/删除习惯用法适用于您的情况。您只需将值移至另一个容器之前
std::remove_if
可能会在谓词中将其打乱: 。Ideone 上的实时示例。(我直接使用
bool
来使代码更短,而不是担心输出等问题。)You can actually make the erase/remove idiom usable for your case. You just need to move the value over to the other container before
std::remove_if
possibly shuffles it around: in the predicate.Live example on Ideone. (I directly used
bool
s to make the code shorter, not bothering with output and the likes.)函数 std::vector::erase 要求迭代器是该向量的迭代器,但您正在从 temp_list 传递迭代器。您无法从一个容器中删除位于完全不同容器中的元素。
The function
std::vector::erase
requires the iterators to be iterators into this vector, but you are passing iterators fromtemp_list
. You cannot erase elements from a container that are in a completely different container.您尝试从一个列表中删除元素,但对第二个列表使用迭代器。第一个列表迭代器与第二个列表中的迭代器不同。
You try to erase elements from one list, but you use iterators for second list. First list iterators aren't the same, like in second list.
我想建议这是应该使用
std::list
的示例。您可以将一个列表中的成员拼接到另一个列表中。请参阅 std::list::splice() 了解这一点。您需要随机访问吗?如果没有,那么您不需要
std::vector
。请注意,对于列表,当您拼接时,迭代器和对列表中对象的引用仍然有效。
如果您不介意使实现“侵入”,您的对象可以包含它们自己的迭代器值,这样它们就知道它们在哪里。然后,当它们改变状态时,它们可以自动从一个列表“移动”到另一个列表,并且您不需要为它们遍历整个列表。 (如果您希望稍后进行此扫描,您可以让它们“注册”自己以供稍后移动)。
我现在将在这里编写一个算法来运行一个集合,如果存在条件,它将影响 std::remove_if 但同时会将元素复制到您的“插入器”中。
这有点像 std::remove_if ,但会将要删除的内容复制到替代集合中。您可以像这样调用它(对于向量),其中 isInactive 是一个有效谓词,指示它应该被移动。
I would like to suggest that this is an example of where
std::list
should be used. You can splice members from one list to another. Look at std::list::splice()for this.Do you need random access? If not then you don't need a
std::vector
.Note that with list, when you splice, your iterators, and references to the objects in the list remain valid.
If you don't mind making the implementation "intrusive", your objects can contain their own iterator value, so they know where they are. Then when they change state, they can automate their own "moving" from one list to the other, and you don't need to transverse the whole list for them. (If you want this sweep to happen later, you can get them to "register" themselves for later moving).
I will write an algorithm here now to run through one collection and if a condition exists, it will effect a std::remove_if but at the same time will copy the element into your "inserter".
This is a bit like
std::remove_if
but will copy the ones being removed into an alternative collection. You would invoke it like this (for a vector) where isInactive is a valid predicate that indicates it should be moved.您传递给
erase()
的迭代器应指向vector
本身;这个断言告诉你他们没有。此版本的erase()
用于擦除向量
中的某个范围。您需要自己迭代
temp_list
,并在每一步取消引用迭代器的结果上调用active.erase()
。The iterators you pass to
erase()
should point into thevector
itself; the assertion is telling you that they don't. This version oferase()
is for erasing a range out of thevector
.You need to iterate over
temp_list
yourself and callactive.erase()
on the result of dereferencing the iterator at each step.