vector內存增長方式


首先必須要了解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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM