首先必须要了解vector是一种特殊的数组,因此其内存必然是连续的

其次它的连续是建立在不断地对内存的预分配上的,即不断地销毁当前,重新建立内存,效率有点低。所以存在几个函数capacity, size

一、前言

首先说明,vector可以理解为动态数组,既然是数组,那么它在内存中就应该是一块连续的内存,但vector是如何支持动态增长的呢?关于这个问题,网上有很对说法,但其中有些说法是错误的,最近看到有一篇博友的解释就非常正确vector空间动态增长,这里就针对的他的解释进行进一步的阐述,并进行实际验证。

二、vector内存增长方式

C++primer中多次明确指出对vector使用的建议是:先创建一个空的vector对象,然后再运行时再利用vector的成员函数push_back向其中添加元素。先以此来验证vector的内存的自动增长,程序说明为:创建一个空的vector a,然后采用push_back向其中添加元素,共迭代10次,运行环境为VS2010IDE

#include <iostream>

#include <vector>

using namespace std;

int main()

{

vector<int> a;

cout << "a.size(): " << a.size() << "       a.capacity(): " << a.capacity() << endl;

for (int i = 0; i < 10; i++)

{

a.push_back(i);

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

}

return 0;

}

运行结果为:

在分析结果之前,首先介绍与vector的内存布局,然后再介绍与内存增长相关的四个函数,分别为size()、capacity()、reserve()、resize()函数。

(1)vector内存布局

start迭代器指向已用空间的首元素,finish指向已用空间的尾元素的下一个位置,end_of_storage指向可用空间的末尾。

(2)size()、capacity()、reserve()、resize()函数

size()函数返回的是已用空间大小,capacity()返回的是总空间大小,capacity()-size()则是剩余的可用空间大小。当size()和capacity()相等,说明vector目前的空间已被用完,如果再添加新元素,则会引起vector空间的动态增长。reserve(n)预先分配一块较大的指定大小的内存空间,其中n为分配空间大小;resize()成员函数只改变元素的数目,不改变vector的容量。

再看刚刚的运行结果,首先可以确定,在VS2010的编译器里面每次并不是增长固定的内存,可以看出是增长当前内存的一半。而且由于我们的程序没有调用reserve(n)函数预先分配一块内存,所以内存增长是编译器自动完成的。这个自动增长包括重新分配内存空间、拷贝原空间、释放原空间三个过程,具体策略为当添加元素时,如果vector空间大小不足,则会以原大小的1.5倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。也就是说vector的空间动态增加大小,并不是在原空间之后的相邻地址增加新空间,因为vector的空间是线性连续分配的,不能保证原空间之后有可供配置的空间。这就解释了上述程序的运行结果。

但是,针对以上自动完成的内存增长过程,由于包括重新分配内存空间、拷贝原空间、释放原空间等步骤,这些过程会降低程序效率,因此可以使用reserve(n)预先分配一块较大的指定大小的内存空间,这样当指定大小的内存空间未使用完时,是不会重新分配内存空间的,这样便提升了效率。下面对上一个程序进行扩展如下,即再定义一个vector b,预先分配10个内存,进行11次push_back操作

#include <iostream>

#include <vector>

using namespace std;

int main()

{

vector<int> a;

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

for (int i = 0; i < 10; i++)

{

a.push_back(i);

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

}

cout << endl;

vector<int> b;

b.reserve(10);

for (int i = 0; i < 10; i++)

{

b.push_back(i);

cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;

}

b.push_back(11);

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

cout << endl;

return 0;

}

运行结果如下:

可以看到,在调用了reserve(10)进行预先内存分配之后,前10次push_back操作vector b 的capacity并没有增长,但是在第11次push_back操作时,由于当前b的size() > capacity(),所以vector自动进行了内存扩充,由10变为15(1.5倍)。也就是说,前10次能避免每次都进行内存扩充,能有效提高效率,但是第11次就不会。但有一点要注意,如果在当前容量没有用完的情况下,再一次调用reserve(n)函数时,只有当n > 当前capacity()时,vector当前容量才会改变。再对上述程序进行扩展,分别加上b.reserve(13)和reserve(20),如下

#include <iostream>

#include <vector>

using namespace std;

int main()

{

vector<int> a;

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

for (int i = 0; i < 10; i++)

{

a.push_back(i);

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

}

cout << endl;

vector<int> b;

b.reserve(10);

for (int i = 0; i < 10; i++)

{

b.push_back(i);

cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;

}

b.push_back(11);

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

cout << endl;

b.reserve(13);

cout << "after b.reserve(13):" << endl;

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

b.reserve(20);

cout << "after b.reserve(20):" << endl;

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

return 0;

}

运行结果为:

可以看到,在加上b.reserve(13),容器b的capacity并没有由15变为13,但加上 b.reserve(20)时却变化了;这也验证了上述结论。

对于resize()成员函数只改变元素的数目,不改变vector的容量的说法可以从下面的程序进行验证:

#include <iostream>

#include <vector>

using namespace std;

int main()

{

vector<int> a;

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

for (int i = 0; i < 10; i++)

{

a.push_back(i);

cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;

}

cout << endl;

vector<int> b;

b.reserve(10);

for (int i = 0; i < 10; i++)

{

b.push_back(i);

cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;

}

b.push_back(11);

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

cout << endl;

b.reserve(13);

cout << "after b.reserve(13):" << endl;

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

b.resize(5);

cout << "after b.resize(5):" << endl;

cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;

for (int i = 0; i < b.size(); i++)

{

cout << b[i] << endl;

}

return 0;

}

运行结果为:

可以看到,在加上resize(5)之后,容器的capacity()并没有增长,只是size()变为了5,而且通过打印vector元素可知,只截取了前五个元素。

————————————————

版权声明:本文为CSDN博主「赵同学」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_26849233/article/details/70738621

一、前言
    首先说明,vector可以理解为动态数组,既然是数组,那么它在内存中就应该是一块连续的内存,但vector是如何支持动态增长的呢?关于这个问题,网上有很对说法,但其中有些说法是错误的,最近看到有一篇博友的解释就非常正确vector空间动态增长,这里就针对的他的解释进行进一步的阐述,并进行实际验证。
二、vector内存增长方式
   C++primer中多次明确指出对vector使用的建议是:先创建一个空的vector对象,然后再运行时再利用vector的成员函数push_back向其中添加元素。先以此来验证vector的内存的自动增长,程序说明为:创建一个空的vector a,然后采用push_back向其中添加元素,共迭代10次,运行环境为VS2010IDE
#include <iostream>#include <vector>using namespace std;int main(){    vector<int> a;    cout << "a.size(): " << a.size() << "       a.capacity(): " << a.capacity() << endl;    for (int i = 0; i < 10; i++)    {        a.push_back(i);        cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    }    return 0;}运行结果为:

在分析结果之前,首先介绍与vector的内存布局,然后再介绍与内存增长相关的四个函数,分别为size()、capacity()、reserve()、resize()函数。
(1)vector内存布局

start迭代器指向已用空间的首元素,finish指向已用空间的尾元素的下一个位置,end_of_storage指向可用空间的末尾。
(2)size()、capacity()、reserve()、resize()函数

size()函数返回的是已用空间大小,capacity()返回的是总空间大小,capacity()-size()则是剩余的可用空间大小。当size()和capacity()相等,说明vector目前的空间已被用完,如果再添加新元素,则会引起vector空间的动态增长。reserve(n)预先分配一块较大的指定大小的内存空间,其中n为分配空间大小;resize()成员函数只改变元素的数目,不改变vector的容量。    再看刚刚的运行结果,首先可以确定,在VS2010的编译器里面每次并不是增长固定的内存,可以看出是增长当前内存的一半。而且由于我们的程序没有调用reserve(n)函数预先分配一块内存,所以内存增长是编译器自动完成的。这个自动增长包括重新分配内存空间、拷贝原空间、释放原空间三个过程,具体策略为当添加元素时,如果vector空间大小不足,则会以原大小的1.5倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。也就是说vector的空间动态增加大小,并不是在原空间之后的相邻地址增加新空间,因为vector的空间是线性连续分配的,不能保证原空间之后有可供配置的空间。这就解释了上述程序的运行结果。    但是,针对以上自动完成的内存增长过程,由于包括重新分配内存空间、拷贝原空间、释放原空间等步骤,这些过程会降低程序效率,因此可以使用reserve(n)预先分配一块较大的指定大小的内存空间,这样当指定大小的内存空间未使用完时,是不会重新分配内存空间的,这样便提升了效率。下面对上一个程序进行扩展如下,即再定义一个vector b,预先分配10个内存,进行11次push_back操作#include <iostream>#include <vector>using namespace std;int main(){    vector<int> a;    cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    for (int i = 0; i < 10; i++)    {        a.push_back(i);        cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    }    cout << endl;    vector<int> b;    b.reserve(10);    for (int i = 0; i < 10; i++)    {        b.push_back(i);        cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;    }    b.push_back(11);    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;    cout << endl;    return 0;}运行结果如下:
    可以看到,在调用了reserve(10)进行预先内存分配之后,前10次push_back操作vector b 的capacity并没有增长,但是在第11次push_back操作时,由于当前b的size() > capacity(),所以vector自动进行了内存扩充,由10变为15(1.5倍)。也就是说,前10次能避免每次都进行内存扩充,能有效提高效率,但是第11次就不会。但有一点要注意,如果在当前容量没有用完的情况下,再一次调用reserve(n)函数时,只有当n > 当前capacity()时,vector当前容量才会改变。再对上述程序进行扩展,分别加上b.reserve(13)和reserve(20),如下#include <iostream>#include <vector>using namespace std;int main(){    vector<int> a;    cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    for (int i = 0; i < 10; i++)    {        a.push_back(i);        cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    }    cout << endl;    vector<int> b;    b.reserve(10);    for (int i = 0; i < 10; i++)    {        b.push_back(i);        cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;    }    b.push_back(11);    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;    cout << endl;      b.reserve(13);    cout << "after b.reserve(13):" << endl;    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  b.reserve(20);    cout << "after b.reserve(20):" << endl;    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;    return 0;}运行结果为:
 可以看到,在加上b.reserve(13),容器b的capacity并没有由15变为13,但加上 b.reserve(20)时却变化了;这也验证了上述结论。   对于resize()成员函数只改变元素的数目,不改变vector的容量的说法可以从下面的程序进行验证:#include <iostream>#include <vector>using namespace std;int main(){    vector<int> a;    cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    for (int i = 0; i < 10; i++)    {        a.push_back(i);        cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;    }    cout << endl;    vector<int> b;    b.reserve(10);    for (int i = 0; i < 10; i++)    {        b.push_back(i);        cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;    }    b.push_back(11);    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;    cout << endl;     b.reserve(13);    cout << "after b.reserve(13):" << endl;    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;     b.resize(5);    cout << "after b.resize(5):" << endl;    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl; for (int i = 0; i < b.size(); i++)    {        cout << b[i] << endl;    }    return 0;}运行结果为:
可以看到,在加上resize(5)之后,容器的capacity()并没有增长,只是size()变为了5,而且通过打印vector元素可知,只截取了前五个元素。————————————————版权声明:本文为CSDN博主「赵同学」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_26849233/article/details/70738621

vector内存增长方式的更多相关文章

  1. C++的STL中vector内存分配方法的简单探索

    STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux  CentOS 5.2 1.代码 #include <vector> #include <stdio ...

  2. windows内存管理方式以及优缺点

    Windows内存管理方式:页式管理,段式管理,段页式管理 页式管理 将各进程的虚拟空间(逻辑地址)划分为若干个长度相等的页,业内管理把内存空间(物理内存)按照页的大小划分为片或者页面,从而实现了离散 ...

  3. c/c++内存分配方式(转)

    原文链接:http://blog.csdn.net/jing0611/article/details/4030237 1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在 程序编译 ...

  4. vector内存回收

    1. vector所有的内存相关问题都可以归结于它的内存增长策略.vector有一个特点就是:内存空间只会增长不会减少.vector有两个函数,一个是capacity(),返回对象缓冲区(vector ...

  5. 内存分配方式,堆区,栈区,new/delete/malloc/free

    1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建.在执行函数时 ...

  6. [转载]C语言程序的内存分配方式

    "声明一个数组时,编译器将根据声明所指定的元素数量为数量为数组保留内存空间."其实就是编译器在编译的过程中,会加入几条汇编指令在程序里处理内存分配,并不是说编译时就分配了内存,不要 ...

  7. C和C++内存分配方式记录

    C. C++中内存分配方式可以分为三种: (1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在.速度快.不容易出错,因为有系统会善后.例如全局变量,static变 ...

  8. C++内存分配方式——(别人的博客)

    http://www.cnblogs.com/easonpan/archive/2012/04/26/2471153.html http://blog.csdn.net/chen825919148/a ...

  9. 【腾讯优测干货分享】如何降低App的待机内存(三)——探索内存增长的原因

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/8BiKIt3frq9Yv9KV5FXlGw 1.3新问题的进一步挖 ...

随机推荐

  1. 30个有关Python的小技巧,给程序员的 30 个基本 Python 贴士与技巧

    30个有关Python的小技巧 2013/07/04 · Python, 开发 · 4 评论 · Python 分享到: 66 本文由 伯乐在线 - Kevin Sun 翻译.未经许可,禁止转载!英文 ...

  2. python简单的函数定义和用法实例

    python简单的函数定义和用法实例 这篇文章主要介绍了python简单的函数定义和用法,实例分析了Python自定义函数及其使用方法,具有一定参考借鉴价值,需要的朋友可以参考下 具体分析如下: 这里 ...

  3. Linux运维工程师前景

    什么是Linux运维 如果我们是一辆高速行驶在高速公路上的汽车,那运维工程师就是司机兼维修工,这个司机可不简单,有时需要在高速行驶过程中更换轮胎.并根据道路情况换档位.当汽车速度越来越快时,汽车本身不 ...

  4. python匿名函数应用--动态计算器

    匿名函数: 一般用于函数体较为简单的运算,和一些不需要函数名的传递.  lambda 参数1:运算举例:  func = lambda x,y:x+y :可以给匿名函数添加变量名. 匿名函数的应用: ...

  5. java序列化的相关介绍

    1.什么是序列化?为什么要用序列化? 序列化就是将对象状态转换为可保持或传输的格式的过程.与序列化相对的就是反序列化,他将流转换成对象.这两个过程结合起来,可以轻松地存储和传输数据. 注意:对象序列化 ...

  6. java_第一年_JDBC(2)

    上篇说到,通过JDBC可实现java编程程序和mysql数据库进行连接并交互,而交互后所形成的结果集是通过ResultSet对象来操作的. 创建ResultSet对象: stmt = conn.cre ...

  7. eclipse 从git取项目,导入为maven项目,新加的方法,报加载主类错误

    eclipse 从git取项目,导入为maven项目,新加的方法,报加载主类错误 具体描述: 整体编译能够编译成功,但新加一个java,里面创建一个main方法,运行时,报无法加载主类的错误, 整体编 ...

  8. 16、NumPy ——字节交换

    NumPy 字节交换 在几乎所有的机器上,多字节对象都被存储为连续的字节序列.字节顺序,是跨越多字节的程序对象的存储规则. 大端模式:指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地 ...

  9. Java 小技巧和在Java避免NullPonintException的最佳方法(翻译)

                前几天就g+里面看到有人引用这篇博文.看了一下.受益颇多. 所以翻译过来,希望和大家一起学习.本人英语水平有限,假设有错,请大家指正. 原文地址(须要翻墙):http://ja ...

  10. Leetcode Lect1 String相关题目

    Java 的 String 类基本用法介绍:http://www.runoob.com/java/java-string.html Java 的 String.substring 函数:https:/ ...