我需要检查 std::map 的数据,并删除其中一些。 我正在使用基于范围的“for”循环,如下所示:
std::map<int, string> data { { 1, "name1" }, { 2, "name2" }, { 3, "name3" }, };
for( auto&[id, name] : data )
if( id == 2 )
data.erase( id );
这个方法正确吗?它会使循环崩溃或导致错误的循环时间吗?
不,这个方法不正确。 range-for 循环在内部使用迭代器来驱动循环。如果通过删除元素来修改
data
,这将使现有迭代器无效并导致未定义的行为。你不能这样做。
你的特定示例有点太微不足道了——甚至没有循环的意义,因为你可以只做
data.erase(2);
而无需搜索整个地图。这样效率也更高。
std::map::erase
的文档包含一个示例,详细说明了如何完成此操作。
如果您确实决定使用 range-for,那么您需要单独存储要擦除的键,然后在第二步中执行此操作。或者,您可以构建一个新地图,并
std::move
将您希望保留的数据放入其中,前提是您不修改原始地图的拓扑。
std::erase_if
——如果循环的唯一目的是验证内容,这将是最好的解决方案。在这种情况下,您可以放弃循环并使用 erase_if
进行验证——这可能是最有效的。
不,这不是正确的方法。您想要学习的模式是:
std::map<int, string> data { { 1, "name1" }, { 2, "name2" }, { 3, "name3" }, };
for(auto it = data.begin(); it != data.end(); )
{
if( it->first == 2 )
{
it = data.erase( it );
}
else
{
it++;
}
}
return 0;
注意循环语句中缺少迭代器增量。相反,我们在删除后更新它,或者以其他方式增加它。