• 条目十四《使用reserve来避免不必要的重新分配》


    条目十四《使用reserve来避免不必要的重新分配》

    使用vector和string的插入元素的时候,我们是不用担心内存问题的(只要不超过容器的max_size)。因为底层有分配子管理内存。在插入元素的时候,内存不够会发生像realloc的过程:

    1. 分配新的内存块,它有容器目前容量的几倍。在大部分实现中,vector和string的容量每次以2为因数增
      长。也就是说,当容器必须扩展时,它们的容量每次翻倍。
    2. 把所有元素从容器的旧内存拷贝到它的新内存。
    3. 销毁旧内存中的对象。
    4. 回收旧内存

    先看个例子

    vector<int> vec;
    for(int i = 0; i < 10; i++)
    {
        vec.push_back(i)
    }
    

    这个过程会发生最少4次重新分配内存的过程。再来看下一个重新分配内存涉及到哪些过程:

    • 1.new操作-->malloc
    • 2.拷贝操作
    • 3.析构对象
    • 4.释放内存

    咋一看,一两次还可以接受,当插入的元素越来越多的时候,对性能的消耗是非常客观的。

    上面的问题还只是其中一个问题,在插入元素时,重新分配内存会造成迭代器、指针和引用的失效。

    为了优化这两个问题,在使用vector和string的时候,可以使用reserve函数。先引出四个关于容器大小和设置的成员函数:

    • size()———————获得容器的元素个数

    • capacity()———获得容器的容量

    • resize()—————强制设置容器的元素个数(参数大于当前大小,调用默认构造函数创建元素填充在尾部。小于当前大小,会析构并销毁多余的元素)

    • reserve()————强制设置容器的容量大小(参数小于现有的容量大小会忽略当前调用,大于会扩容。)

    为了避免容器的不必要扩容而造成的消耗,在初始化容器的时候可以通过reserve()设置容器的容量大小,这样在插入元素的是够,只要当前的元素个数小于容量大小,都不会发生重新分配内存。这样也就不会发生迭代器、指针和引用失效等问题,也就没有多次拷贝,析构对象,释放内存的现象发生。

    vector<int> vec;
    vec.reserve(15);
    for(int i = 0; i < 10; i++)
    {
        vec.push_back(i)
    }
    

    这个过程在reserve后插入元素不会发生重新分配内存过程。因为,插入的元素个数(10)小于容量的大小(15)。

    可能有人说,在开始时设置过多的容量,那么不就相当于数组吗?浪费了剩余没用到内存,不用担心这个问题,我们可以等插入元素完毕的时候:

    • 调用sesize()来修剪大小
    • 使用swap()技巧。(vector tmp_vec(vec).swap(vec) 利用容器的拷贝构造不会复制空内存的原理,先创建一个纯净的临时容器,然后再交换容器内容,原来的容器就可以成为一个没有多余容量的容器,节省内存哦)
  • 相关阅读:
    php的多态性
    php接口
    php抽象类和抽象方法
    php类与对象的魔术方法
    php关键字
    php类型之class类,对象,构造函数的理解
    php日期格式化
    php之常用字符串方法
    php将获取的数组变成字符串传入txt文本。。。
    PHP之键值操作函数
  • 原文地址:https://www.cnblogs.com/liangjf/p/10259684.html
Copyright © 2020-2023  润新知