| 
 | 
 
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册  
 
x
 
#include <iostream> 
#include <string> 
#include <vector> 
 
using namespace std; 
 
int main() 
{ 
         
        vector<int> lst = {1,101,2,303,4,404,6,707,9,909,1001}; 
        auto it = lst.begin(); 
        while(it != lst.end()) 
        { 
                if (*it %2) 
                { 
                        lst.erase(it);    # 在这一行  C++primer中的书写方式是 it = lst.erase(it);  
                } 
                else 
                { 
                        ++it; 
                } 
        } 
        for (auto it1 = lst.begin() ; it1 != lst.end();++it1) 
        { 
                cout << "####################" << endl; 
                cout << *it1 << endl; 
                cout << "####################" << endl; 
        } 
        return 0; 
} 
 
question: 
不写it = 的方式和书写了的方式有何不同? 为什么要写上那一步? 
对于某些比较宽松的编译器,按现版本的vector存储方式,确实结果应该是一样的, 
但这只对vector等少数基于数组存储的容器有效,且仅在某些比较宽松的编译器中有效,(在vs 2017中会报错) 
 
 
需要解释的话,首先了解一下vector是如何存储元素的 
作为一个变长数组,当向其存储数据时,vector会申请一段默认长度的空间,比方说,对于一个储存了{1,2,3}的vector,它内部可能是这样的 
{1,2,3,0},size=3;这个时候,向其添加一个元素4,它会变成这样{1,2,3,4},size=4,这个时候,1,2,3的地址都没有改变,那么指向其的指针均保持有效; 
但是,这个时候再向其添加一个元素5,因为原来的数组已经不够大,vector会申请一段更大的空间,比如int[8],并把原来的元素搬过去,就变成了这样 
{1,2,3,4,5,0,0,0},size=5;这个时候,指向原1,2,3的指针,其地址已经被释放,也就是变成了野指针。 
但是现版本的vector,在删除元素时,并不会发生容量的减少,所以指针总是有效; 
 
但是,迭代器并不仅仅是指针,而是包装了的指针,当你调用erase(it)时,it会直接被标记为“失效”,因而对于某些编译器,会因为你调用了“失效”了的迭代器而报错, 
此外,你并不能保证,在下个版本中,vector不会因为erase而减少容量; 
第三,对于其他容器,比如基于链表的容器,这种用法一定失败。 
 
因此,即使在这个例子中成功了,你也不应该试图调用一个失效了的迭代器 
 
 
 
 
 |   
 
 
 
 |