2016-11-18 55 views
0

如何深度擦除矢量?C++ STL矢量深度擦除

请考虑以下代码。

#include<algorithm> 
#include<iostream> 
#include<iterator> 
#include<vector> 

using namespace std; 

int main(){ 
    vector<int> v {1,2,3,4,5}; 
    for_each(begin(v),end(v),[&v](int& n){ 
     static auto i = (int)0; 
     if(n == 2){ 
      v.erase (begin(v) +2, end(v)); 
     } 
     cout << n << " having index " << i++ << endl; 
    }); 
    v.erase (begin(v) +2, end(v)); 
    cout << v.size() << endl << v[4] << endl; 
} 

输出是

1 having index 0 
2 having index 1 
3 having index 2 
4 having index 3 
5 having index 4 
2 
4 

欲正在访问v实现任意i为2至4是无效的和编译器以引发错误[I]什么。

用简单的话来说,如何深度擦除矢量?

+2

它是UB;你应该自己检查一下。或者使用'std :: vector :: at'。 – songyuanyao

+0

一个向量通过定义将其元素存储在连续内存中,所以你想要的不是可能的 – user463035818

+1

而且你甚至希望它成为编译时错误。 – LogicStuff

回答

1

您正在触发未定义的行为,因此您的结果不可信。

如果您需要检查的边界用std::vector::at

vector<int> v{ 1,2,3,4,5 }; 
v.erase(begin(v) + 2, end(v)); 
try { 
    auto val = v.at(4); 
} catch (std::out_of_range&) { 
    cout << "out of range"; 
} 

除非你编写自己的设备或解决方法,你不能有这样的编译时检查与std::vector。更多的信息和一些建议在这里:https://stackoverflow.com/a/32660677/1938163

+0

访问运算符[]和方法之间有什么区别? – kalpa

+0

@kalpa'at'确实检查并在超出范围的情况下抛出运行时异常 –

+0

使用'[]'访问向量是否是不好的做法? – kalpa

1

我没有时间现在给出的例子,但我可以认为干净做到这一点的唯一方法是让自定义类包装或子类向量。然后,您可以生成定制的[]at运算符,这些运算符会在某些索引上引发错误。你甚至可以有一个删除方法,添加indeces到这个禁止列表的列表。

现在,如果您在编译时需要这个错误,那就更困难了。我认为使用constexpr接入运营商和一些static_assert s可能是可能的,但我不确定如何离线。

+0

如果operator []产生UB并且没有进行范围检查,那么为什么它被允许? 'at'会增加与'operator []'相比的性能开销吗?如果是的话,它有多重要? – kalpa

+0

@kalpa评论的第二句回答第一个问题,[]存在的速度很慢,具体取决于速度,但我猜测运行时间会延长3-10倍。 – Vality

+0

当我调用'erase'或'clean'方法时,另一件事情是内存解除分配,还是直到整个矢量被销毁才解除分配? – kalpa