vector容器的几个要点

来源:互联网 发布:2016易语言源码大全 编辑:程序博客网 时间:2024/06/06 09:29

1. insert插入和emplace的区别

emplace操作是C++11新特性,新引入的的三个成员emlace_front、empace 和 emplace_back,这些操作构造而不是拷贝元素到容器中,这些操作分别对应push_front、insert 和push_back,允许我们将元素放在容器头部、一个指定的位置和容器尾部。

两者的区别

当调用insert时,我们将元素类型的对象传递给insert,元素的对象被拷贝到容器中,而当我们使用emplace时,我们将参数传递元素类型的构造函数,emplace使用这些参数在容器管理的内存空间中直接构造元素。

insert插入的数据需要经过 栈->寄存器->内存 ,而emplace只需要 寄存器->内存。

例子

假定d是一个Date类型的容器。

//使用三个参数的Date构造函数,在容器管理的内存空间中构造新元素。 d.emplace_back(“2016”,”05”,”26”);//错误,push_back没有这种用法 d.push_back(“2016”,”05”,”26”);//push_back()创建一个临时对象,然后将临时对象拷贝到容器中 d.push_back(Date(“2016”,”05”,”26”));

通过例子发现,使用c++11新特性emplace向容器中添加新元素,在容器管理的内存空间中构造新元素,与insert相比,省去了构造临时对象,减少了内存开销。

2.iterator迭代器失效问题

2.1 插入失效

#include<iostream>#include<vector>using namespace std;int main(){    vector<int> v;    v.push_back(1);    std::vector<int>::iterator iter1 = v.begin();    v.push_back(1);    int n = *iter1;    cout << n << endl;    return 0;}

上面的代码运行时崩溃,就是因为迭代器iter1在vector push_back新值后失效了。切记!
但是为什么会失效?
如果我先预先resize足够大,那么会如何呢?

#include<iostream>#include<vector>using namespace std;int main(){    vector<int> v;    v.resize(4);    v.push_back(1);    std::vector<int>::iterator iter1 = v.begin();    v.push_back(1);    int n = *iter1;    cout << n << endl;    return 0;}

上面的代码正常运行,因为之前resize了足够的空间,即迭代器不会失效。
我们就已给vector push_back两个元素为例。resize(1), resize(2), resize(3)程序还是会崩溃。还是容量不足,导致vector重新分配内存,而导致迭代器失效。

参考博客:http://blog.csdn.net/wangshubo1989/article/details/50334297

2.2删除失效

#include <iostream>#include <vector>using namespace std;typedef vector<int> Vec;typedef vector<int>::iterator VecIt;void print(Vec &v){    VecIt it;    for(it = v.begin(); it != v.end(); it++)    {        cout << *it << " ";    }    cout << endl;}void deleteValueFromVector(Vec &v, int n = 5){    VecIt it;    for(it = v.begin(); it != v.end(); it++)    {        if(0 == *it % n)        {            v.erase(it);        }    }}int main(){    Vec v;    int i = 0;    for(i = 0; i < 21; i++)    {        v.push_back(i); // 不能再傻傻地用下标了    }    print(v);    deleteValueFromVector(v); // 程序崩溃    print(v);    return 0;}
   运行程序, 结果程序也崩溃, 可见, vector删除也存在迭代器失效的问题, 怎么改呢? 如下:
#include <iostream>#include <vector>using namespace std;typedef vector<int> Vec;typedef vector<int>::iterator VecIt;void print(Vec &v){    VecIt it;    for(it = v.begin(); it != v.end(); it++)    {        cout << *it << " ";    }    cout << endl;}void deleteValueFromVector(Vec &v, int n = 5){    VecIt it;    for(it = v.begin(); it != v.end(); /*不能再自增了*/)    {        if(0 == *it % n)        {            v.erase(it); // vector元素自动向前挪动了(关联的map容器元素不会自动挪动), 所以不能再把it进行++了        }        else        {            it++;        }    }}int main(){    Vec v;    int i = 0;    for(i = 0; i < 21; i++)    {        v.push_back(i); // 不能再傻傻地用下标了    }    print(v);    deleteValueFromVector(v); // 程序ok    print(v);    return 0;}
    结果为:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4 6 7 8 9 11 12 13 14 16 17 18 19

    可见, vector迭代器失效的问题也不容忽视。

3.Capacity容量的增长方式

下面我们截取了VS2017编译器中的关于容量增长的源码:

size_type _Calculate_growth(const size_type _ Newsize) const        {   // given _Oldcapacity and _Newsize, calculate geometric growth        const size_type _Oldcapacity = capacity();        if (_Oldcapacity > max_size() - _Oldcapacity / 2)            {            return (_Newsize);  // geometric growth would overflow            }        const size_type _Geometric = _Oldcapacity + _Oldcapacity / 2;        if (_Geometric < _Newsize)            {            return (_Newsize);  // geometric growth would be insufficient            }        return (_Geometric);    // geometric growth is sufficient        }
第一种情况:_Oldcapacity > max_size() - _Oldcapacity / 2  : 当旧容量大于(最大的可能的元素个数 - 旧容量/2)  ,直接返回Newsize大小的容量第二种情况:_Geometric = _Oldcapacity + _Oldcapacity / 2; 即1.5倍旧容量小于Newsize,返回Newsize大小的容量。第三种情况: 排除以上2种情况,返回1.5倍旧容量

参考博客:

map和vector的迭代器失效问题:
http://www.cnblogs.com/yuanshuang/p/5777905.html

实战c++中的vector系列–可怕的迭代器失效(vector重新申请内存):
http://blog.csdn.net/wangshubo1989/article/details/50334297

C++11新特性emplace操作:
http://blog.csdn.net/penghuicheng/article/details/51505625

原创粉丝点击