gpt4 book ai didi

c++ - vector::erase 和 std::remove_if 的奇怪行为,其结束范围不同于 vector.end()

转载 作者:可可西里 更新时间:2023-11-01 18:18:10 28 4
gpt4 key购买 nike

我需要从 std::vector 的中间移除元素。

所以我尝试了:

struct IsEven {
bool operator()(int ele)
{
return ele % 2 == 0;
}
};

int elements[] = {1, 2, 3, 4, 5, 6};
std::vector<int> ints(elements, elements+6);

std::vector<int>::iterator it = std::remove_if(ints.begin() + 2, ints.begin() + 4, IsEven());
ints.erase(it, ints.end());

在此之后,我希望 ints vector 具有:[1, 2, 3, 5, 6]。

在 Visual Studio 2008 的调试器中,在 std::remove_if 行之后,修改了 ints 的元素,我猜我正在做某种事情这里有未定义的行为。

那么,如何从 vector 的范围中删除元素?

最佳答案

编辑:抱歉,这个的原始版本不正确。固定。

这是正在发生的事情。您对 remove_if 的输入是:

1  2  3  4  5  6
^ ^
begin end

并且 remove_if 算法查看 beginend 之间的所有数字(包括 begin,但不包括 end), 并删除与您的谓词匹配的所有元素。所以在 remove_if 运行之后,你的 vector 看起来像这样

1  2  3  ?  5  6
^ ^
begin new_end

? 是一个我认为不是确定性的值,尽管如果保证它是任何值,它将是 4new_endstd::remove_if 返回的内容,它指向您给它的输入序列的新结尾,现在删除了匹配元素。请注意,std::remove_if 不会触及您提供的子序列之外的任何内容。对于更扩展的示例,这可能更有意义。

说这是你的输入:

1  2  3  4  5  6  7  8  9  10
^ ^
begin end

std::remove_if 之后,你得到:

1  2  3  5  7  ?  ?  8  9  10
^ ^
begin new_end

想一想。它所做的是从子序列中删除 4 和 6,然后将子序列中的所有内容 向下移动以填充删除的元素,然后移动 end 迭代器到同一子序列的新末端。目标是满足其生成的 (begin, new_end] 序列与 (begin, end] 您传入的子序列,但删除了某些元素。您传入的 end 处或之后的任何内容都保持不变。

然后,您想要摆脱的是返回的结束迭代器和您给它的原始结束迭代器之间的所有内容。这些是 ?“垃圾”值。所以你的删除调用实际上应该是:

ints.erase(it, ints.begin()+4);

您刚才调用的 erase 会删除执行删除操作的子序列末尾以外的所有内容,这不是您想要的。

让事情变得复杂的是 remove_if 算法实际上并没有在 vector 上调用 erase(),也没有在任何时候改变 vector 的大小。它只是移动元素并在您要求它处理的子序列结束后留下一些“垃圾”元素。这看起来很愚蠢,但 STL 这样做的全部原因是为了避免 doublep 带来的无效迭代器的问题(并且能够在不是 STL 容器的东西上运行,比如原始数组)。

关于c++ - vector::erase 和 std::remove_if 的奇怪行为,其结束范围不同于 vector.end(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2717012/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com