首先必须要了解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. threading.get_ident()

    https://docs.python.org/3/library/threading.html Return the 'thread identifier' of the current threa ...

  2. Vagrant 手册之 Vagrantfile - 最低版本

    原文地址 可以在 Vagrantfile 中指定一组 Vagrant 的版本,以强制人们使用带有 Vagrantfile 的特定版本的 Vagrant.这可以帮助解决使用带有 Vagrantfile ...

  3. Nginx 转写功能和Apache .htaccess 对应

    之前一直使用apache 服务器,现有一项目想转到Nginx 服务器运行.. 发现Apache 的撰写功能和 Nginx的不一样.无法通用.hataccess 文件 查阅网上资料,nginx 配置转写 ...

  4. Ubuntu12.04下安装Subversion并进行配置

    Ubuntu下安装Subversion还是很简单的,只要输入sudo apt-get install Subversion就可以安装了. 主要的难点在于对权限的配置上. 安装完subversion后, ...

  5. Using Keyboard Navigation

    http://technet.microsoft.com/en-us/library/cc939835.aspx

  6. Thinkphp在nginx设置同域名二级目录访问

    Thinkphp在nginx设置同域名二级目录访问,是因为最近弄一个小程序项目,要https,但是只有单个域名,不能通配域名,所有只好用二级目录,thinkphp二级目录访问要怎么设置呢 下面是ngi ...

  7. Pull Request的正确打开方式(如何在GitHub上贡献开源项目)

    Pull Request的正确打开方式(如何在GitHub上贡献开源项目) GitHub的官方帮助如下: Fork A Repo: https://help.github.com/articles/f ...

  8. 20191101php日期练习

    <?phpecho abs(-23);echo "<hr/>";echo date("t");echo "<hr/>&q ...

  9. Css中的!important

    转载自:https://www.cnblogs.com/cang12138/p/7326280.html !important为开发者提供了一个增加样式权重的方法,比直接在元素的 style 属性中设 ...

  10. 【知识强化】第五章 中央处理器 5.1 CPU的功能和基本结构

    那么在前四章我们已经把数据的表示和运算,存储系统和指令系统都已经给大家讲完了.那么从这一章开始,我们将要讲解中央处理器的内容.那么这一部分内容我们就进入到我们计算机组成原理的一个深水区,它是我们计算机 ...