关于如何快速释放STL容器vector元素的问题探究

落花浮王杯 提交于 2019-12-02 06:20:32

       因项目需要在某些时间节点擦除vector所包含的内容,之前了解到STL的vector具有clear函数,拿来直接使用,结果代码会出现迭代器越界的错误,故对这部分进行了一番探究,当然是先翻各路大神的博客,大概得到几个结论,我将在结论下方附上验证过程:

1.clear函数做的事情是通过迭代器,从begin遍历到到end,过程中如果vector所储存的是对象,那么将会调用该对象的析构函数,此处需要注意的是如果存储的是指针那么将不会调用指针对应对象的析构函数,之后容器内的元素将被清空,但是容器实际占用内容不会被释放;

//vector for class
class ptrclass{
public:
    ptrclass(){
        cout << "Access the ptrclass()" << endl;
    }
    ~ptrclass(){
        cout << "Access the ~ptrclass()" << endl;
    }
};
int main(int argc, char** argv){
    vector<ptrclass> ptcla;
    ptrclass* pcl1 = new ptrclass();
    ptrclass* pcl2 = new ptrclass();
    ptrclass* pcl3 = new ptrclass();
    ptcla.push_back(*pcl1);
    ptcla.push_back(*pcl2);
    ptcla.push_back(*pcl3);
    ptcla.clear();
    /*vector<ptrclass>::iterator itcls = ptcla.begin()    
    while(itcls != ptcla.end()){
        ptcla.erase(itcls);
    }*/
}

运行结果如下,说明调用了对象的析构函数:

修改代码验证clear不能释放容器占用内存

int main(int argc, char** argv){    
    vector<string> vstr;
    string s1 = "woshia1";
    string s2 = "woshia2";
    vstr.push_back(s1);
    vstr.push_back(s2);
    cout << "ele1-addr:" << &vstr[0] << endl;
    cout << "ele2-addr:" << &vstr[1] << endl;
    cout<<vstr.empty()<<endl;
    cout<<vstr.size()<<endl;
    cout<<vstr.capacity()<<endl;
    cout<< "Before clear, the Gap of begin to end:" << vstr.end() - vstr.begin() << endl;
    vstr.clear();
    cout<< "the Gap of begin to end:" << vstr.end() - vstr.begin() << endl;
	cout << "vstr[0]:" << vstr[0].c_str() << endl;
    cout<<vstr.empty()<<endl;
    cout<<vstr.size()<<endl;
    cout<<vstr.capacity()<<endl;
    getchar();
    return 0;
}

       代码使用g++4.8进行编译可以正常输出结果

       但是在vs2010上运行,得到断言

       但是因为该vector的capacity仍然保持为2,所以clear函数未能释放内存的结论仍然成立,VS只不过做了优化的工作,对STL的用法检查较为严格,禁止采用数组方式访问执行过clear的vector内元素。

2.erase函数针对单一元素的表现和clear函数一致;

3.swap函数用来执行交换,使用时头文件需要包含<algorithm>,当需要释放内存时,可如下操作:

int main(int argc, char**argv){
    vector<string> vstr;  //需要释放的容器
    string s1 = "woshia1";
    string s2 = "woshia2";
    vstr.push_back(s1);
    vstr.push_back(s2);
    cout <<&vstr[0] <<endl;
    cout <<&vstr[1] <<endl;    

    cout<<vstr.empty()<<endl;
    cout<<vstr.size()<<endl;
    cout<<vstr.capacity()<<endl;
    
    vector<string> vstr2;
    swap(vstr, vstr2);
    //vector<int>().swap(obj);  //一个更加优雅的写法
    cout<<vstr.empty()<<endl;
    cout<<vstr.size()<<endl;
    cout<<vstr.capacity()<<endl;
    cout<<vstr2.empty()<<endl;
    cout<<vstr2.size()<<endl;
    cout<<vstr2.capacity()<<endl;
    cout <<&vstr2[0] <<endl;
    cout <<&vstr2[1] <<endl;
    return 0;
}

    

     结果如图:

       说明swap另目标容器指向了新初始化的容器vstr2,二者对调,容器vstr2的元素指针与之前vstr元素指针一致,结论成立。

       因此,可以在函数体内通过建立局部变量并执行swap函数的方式快速释放掉原容器占用内存,而我之前出现iterator越界的错误,则是因为访问了已经clear掉的元素。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!