对 2D 或 3D 向量使用擦除删除习语

Posted

技术标签:

【中文标题】对 2D 或 3D 向量使用擦除删除习语【英文标题】:Using the erase-remove idiom for 2D or 3D vectors 【发布时间】:2015-11-27 05:46:06 【问题描述】:

当我尝试将vector.erase() 用于循环内的二维向量时,我遇到了分段错误。代码如下:

vector<vector<int> > fault;
...
...
for(i=0; i<10; i++)

    for(j=0; j<fault.size(); j++)
    
        if(pointer[i].val == fault[j][0])
            fault.erase(fault.begin() + j); //ERROR HERE!
    

是不是因为向量故障的大小发生了变化?我可以在这里使用擦除删除成语吗?如果是这样,我会怎么做? 非常感谢!

【问题讨论】:

我在这里看不到任何会导致问题的东西,除非 pointer 数组少于 10 个元素。 (请注意,当您从错误中删除元素 j 时,您的下一次循环迭代将跳过向下移动的元素以替换已删除的元素。) 感谢您指出这一点! Pointer 总是有 10 个元素。我尝试调试错误,发现fault.erase() 在vector.h 中输入了某个函数并没有退出。 您必须提供一个最小的示例,就目前而言,您的问题被认为是题外话。请阅读指南,它们还给出了这些规则的理由。也就是说,将您想要保留的那些元素复制到一个新向量(预先保留足够的空间)然后与前一个向量交换会更容易且通常更高效。 【参考方案1】:

代码不会导致您提到的行出现分段错误。

可能是 if 语句导致了分段错误。要么是因为 pointer 不包含 10 个有效元素,要么是因为 fault 在它包含的所有向量中都没有元素 0(零)。

您可以尝试添加此检查:

for(i=0; i<10; i++)

    for(j=0; j<fault.size(); j++)
    
        if (fault[j].size() > 0)
        
            if(pointer[i].val == fault[j][0])
                fault.erase(fault.begin() + j);
        
    

顺便说一句,您的逻辑似乎是错误的,因为您没有测试向量中的所有元素,即当您删除一个元素时,将为下一个元素跳过测试。也许你会需要这个:

for(i=0; i<10; i++)

    for(j=0; j<fault.size(); )
    
        if((fault[j].size()>0) && (pointer[i].val == fault[j][0]))
        
            fault.erase(fault.begin() + j);
        
        else
        
           // Only increment when no erase is done
           j++;
        
    

【讨论】:

非常感谢!我对 C++ 很陌生,这帮助我学到了很多东西。出于好奇,是否可以将擦除删除习语用于多维向量?我在网上查了,但没有找到任何例子。

以上是关于对 2D 或 3D 向量使用擦除删除习语的主要内容,如果未能解决你的问题,请参考以下文章

使 C++ 模拟类同时使用 2D 和 3D 向量

C ++中的擦除插入习语?

在向量中使用擦除时双重释放或损坏(fasttop)。知道它们的索引,你怎么能擦除向量的几个项目?

从向量中最快擦除元素或更好地使用内存(排序基数)

将 3D MatND 拆分为 2D Mat opencv 的向量

3D数学基础向量