使用reserve要再次避免不必要的分配



关于STL容器,最了不起的一点是,它们会自己主动增长以便容纳下你放入当中的数据,仅仅要没有超出它们的最大限制就能够。对于vector和string,增长过程是这样来实现的:每当须要很多其它空间时,就调用与realloc类似的操作。

这一类似于realloc的操作分为4部分:

  1. 分配一块大小为当前容量的某个倍数的新内存。

    在大多数实现中,vector和string的容量每次以2的倍数增长,即,每当容器须要扩张时,它们的容量即加倍。

  2. 把容器的全部元素从旧的内存复制到新的内存中。
  3. 析构掉旧内存中的对象。
  4. 释放旧内存。

    reserve成员函数能使你把又一次分配的次数降低到最低限度,从而避免了又一次分配内存和指针/迭代器/引用失效带来的开销。在解释reserve如何做到这一点之前。我将简单概括一下4个相互关联,但有时会被混淆的成员函数。在标准容器中,仅仅有vector和string提供了全部这4个函数:

    size()说明了改容器中有多少个元素。它不会告诉你该容器为自己所包括的元素分配了多少内存。

    capacity()说明了改容器利用已经分配的内存能够容纳多少个元素。

    这是容器所能容纳的元素总数。而不是它还能容纳多少个元素。

    假设你想知道一个vector由多少为被使用的内存,你就得从capacity()中减去size()。假设size和capacity返回相同的值。就说明容器中不再有剩余空间了。

    resize(Container::size_type n)强迫容器改变到包括n个元素的状态。

    在调用resize之后,size将返回n。

    假设n比当前的大小要小,则容器尾部的元素将会被析构掉。假设n比当前的大小要大。则通过默认构造函数创建的新元素将被加入到容器的末尾。假设n比当前的容量要大,那么在加入元素之前,将先又一次分配内存。

    reserve(Container::size_type n)强迫容器把它的容量变为至少是n。前提是n不小于当前的大小。这一般会导致又一次分配,由于容量会添加。(假设n比当前的容量小,则vector忽略该调用。什么也不做;而string则可能把自己的容量减为size()和n中的最大值,可是string的大小肯定保持不变。)

    比如:假定想创建一个包括1到1000之间的值的vector<int>。

    假设不使用reserve。你可能会这样做:

    vector<int> v;

    for (int i = 1;i <= 1000;++i)

    v.push_back(i);

    该循环在进行过程中将导致2到10次又一次分配。假设使用reserve,例如以下所看到的:

    vector<int> v;

    v.reserve(1000);

    for (int i = 1;i <= 1000;++i)

    v.push_back(i);

    则在循环过程中将不会再发生又一次分配。

假设想除去多余的容量。请參阅怎样有效除去多余的容量

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-10-14 20:47:07

使用reserve要再次避免不必要的分配的相关文章

Effective STL: 使用reserve来避免不必要的内存分配

使用reserve来避免不必要的内存分配 当确切或大约知道有多少元素将最后出现在容器中 vector<int> v; // 如果此处不用reserve来先出发内存分配,下面的循环会出现多次内存的重新分配(涉及到分配.回收.拷贝.析构等耗费昂贵的动作) v.reserve(1000); for (int i = 1; i <= 1000; ++i) { v.push_back(i); } 保留你可能需要的最大的空间,然后,一旦你添加完全部数据,修整掉任何多余的容量(可以考虑用swap来修整

使用reserve来避免不必要的重新分配

 关于STL容器,最了不起的一点是,它们会自动增长以便容纳下你放入其中的数据,只要没有超出它们的最大限制就可以.对于vector和string,增长过程是这样来实现的:每当需要更多空间时,就调用与realloc类似的操作.这一类似于realloc的操作分为4部分: 分配一块大小为当前容量的某个倍数的新内存.在大多数实现中,vector和string的容量每次以2的倍数增长,即,每当容器需要扩张时,它们的容量即加倍. 把容器的所有元素从旧的内存拷贝到新的内存中. 析构掉旧内存中的对象. 释放旧

c++ String 类函数详解

c++ String 类函数详解 总算抽出时间把string类里的函数好好研究一遍,在VS2013里完整运行了一遍,加深了一下理解: 代码块 #include < iostream > #include < string > using namespace std; void main() { string s = "asdssfghjkl"; char a1; string::iterator it; string::const_iterator cit; s

Android中直播视频技术探究之---基础核心类ByteBuffer解析

一.前言 前一篇文章我们介绍了Android中直播视频技术的基础大纲知识,这里就开始一一讲解各个知识点,首先主要来看一下视频直播中的一个重要的基础核心类:ByteBuffer,这个类看上去都知道了,是字节缓冲区处理字节的,这个类的功能非常强大,也在各个场景都有用到,比如网络数据底层处理,特别是结合网络通道信息处理的时候,还有就是后面要说到的OpenGL技术也要用到,当然在视频处理中也是很重要的,因为要处理视频流信息,比如在使用MediaCodec进行底层的视频流编码的时候,处理的就是字节,我们如

深入研究java.lang.Runtime类

深入研究java.lang.Runtime类 一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用.      一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为.

Linux集群系列之一——集群基础概念

PHP高级工程师之LInux集群(多态主机组合起来,完成一个任务) 在这里和大家分享一下多数网络黑客常用的攻击方式及预防措施. 如有不善,多提意见(QQ:1595068971-邮箱:[email protected]) 负载均衡集群LB(提高服务的病发处理能力为根本)增加处理能力 衡量标准: 病发处理能力(一次性能够处理多少个请求) 高可用集群HA(提升服务的始终在线能力为根本,不会因为宕机而导致服务不可用)增加服务可用性 衡量标准:在线时间 / (在线时间+故障处理时间) 99%,99.9%,

STL—vector空间的动态增长

vector空间的动态增长 当添加元素时,如果vector空间大小不足,则会以原大小的两倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间.vector的空间动态增加大小,并不是在原空间之后的相邻地址增加新空间,因为vector的空间是线性连续分配的,不能保证原空间之后有可供配置的空间.因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就会失效. vector的size(),capacity(),reserve(),

C++:vector的用法详解(转载)

原文地址:http://blog.csdn.net/hancunai0017/article/details/7032383 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的. 用法: 1.文件包含: 首先在程序开头处加上#include<vector>以包含所需要的类文件vector 还有一定要加上using namespace std; 2.变量声明: 2.1 例:

浅析Java.lang.Runtime类

一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用.      一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为.       当Applet和其他不被信任的代