vector的resize與reserve
reserve()函數為當前vector預留至少共容納size個元素的空間.(譯注:實際空間可能大於size)
resize() 函數( void resize( size_type size, TYPE val ) )改變當前vector的大小為size,且對新創建的元素賦值val
(翻譯:
調整容器大小以包含count元素。
如果當前大小大於count,則容器將被縮減為其第一個count元素,就像重復調用pop_back()一樣。
如果當前大小小於count,則附加元素並用值的副本初始化。)
resize和reserve函數本質都涉及了vector的內存存儲空間,因為vector在內存中是連續存放的,所以當resize的空間大於現有的存儲空間(capacity() 函數 返回當前vector在重新進行內存分配以前所能容納的元素數量.)時,會重新選擇更大的空間,並將所有元素復制過去。resize在初始化內存容量時有對值的初始化,所以此時push_back會產生size+1,內存容量不夠,重新尋找更大的內存空間並復制所有元素,所以這個過程是很費事的。
void testResize(){
vector<int> vector1;
vector1.resize(10);
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
cout<<"vector1的長度:"<<vector1.size()<<endl;//vector1的長度:13
for_each(vector1.begin(),vector1.end(),[](int x){cout<<x<<" ";});//0 0 0 0 0 0 0 0 0 0 1 2 3
cout<<endl<<"當前vector在重新進行內存分配以前所能容納的元素數量:"<<vector1.capacity()<<endl;//20
}
void testReserve(){
vector<int> vector1;
vector1.reserve(10);
vector1.push_back(1);//vector1的長度:3
vector1.push_back(2);//1 2 3
vector1.push_back(3);
cout<<"vector1的長度:"<<vector1.size()<<endl;//vector1的長度:3
for_each(vector1.begin(),vector1.end(),[](int x){cout<<x<<" ";});// 1 2 3
cout<<endl<<"當前vector在重新進行內存分配以前所能容納的元素數量:"<<vector1.capacity()<<endl;//10
}
插入測試
接下來探討插入的效率的實例,分別嘗試在插入大數據3.8GB和小數據380MB時,各種情況的實現。
(1)push_back直接插入
結論:費事,在插入的過程中,不斷尋找“庇護所”,不斷“遷移大本營”,舟車勞頓效率低下
void testPushBack_bigsize(){
vector<int> vector1;
clock_t start = clock();
for (int i = 0; i < 1000000000; ++i) {//3814MB
vector1.push_back(i);
}
cout <<"共耗時:"<< (clock() - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:42s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000000 capacity:1073741824
clock_t start2 = clock();
vector1.push_back(1);
cout <<"共耗時:"<< (clock() - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:0s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000001 capacity:1073741824
}
(2)先reserve在push_back
結論:先分配空間再進行后續處理,能夠有效的減少插入時間的損耗,耗時占原插入方式的1/3到1/2之間。
void testPushBack_byReserve_bigsize(){
vector<int> vector1;
vector1.reserve(1000000000);//3814MB
clock_t start = clock();
for (int i = 0; i < 1000000000; ++i) {
vector1.push_back(i);
}
cout <<"共耗時:"<< (clock() - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:17s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000000 capacity:1000000000
clock_t start2 = clock();
vector1.push_back(1);
cout <<"共耗時:"<< (clock() - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:76s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000001 capacity:2000000000
}
void testPushBack_byReserve_smallsize(){
vector<int> vector1;
vector1.reserve(100000000);//381MB
clock_t start = clock();
for (int i = 0; i < 100000000; ++i) {
vector1.push_back(i);
}
cout <<"共耗時:"<< (clock() - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:1s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:100000000 capacity:100000000
clock_t start2 = clock();
vector1.push_back(1);
cout <<"共耗時:"<< (clock() - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:2s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:100000001 capacity:200000000
}
(2)先resize在利用坐標進行賦值(相當於插入)
結論:在分配空間時直接對空間進行初始化,賦予初值,極大提升了存儲的速率。但是在resize后進行push_back是不明智的選擇。
void testinsert_byResize_bigsize(){
vector<int> vector1;
vector1.resize(1000000000);
clock_t start = clock();
for (int i = 0; i < 1000000000; ++i) {
vector1[i]=i;
}
cout <<"共耗時:"<< (clock() - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:3s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000000 capacity:1000000000
clock_t start2 = clock();
vector1.push_back(1);
cout <<"共耗時:"<< (clock() - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:66s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000001 capacity:2000000000
}
void testinsert_byResize_smallsize(){
vector<int> vector1;
vector1.resize(100000000);
clock_t start = clock();
for (int i = 0; i < 100000000; ++i) {
vector1[i]=i;
}
cout <<"共耗時:"<< (clock() - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:0s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:size:10000000 capacity:10000000
clock_t start2 = clock();
vector1.push_back(1);
cout <<"共耗時:"<< (clock() - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗時:2s
cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:10000001 capacity:20000000
}
vector優化結論
防止reallocate內存,而導致的數據拷貝產生的額外耗時
vector在push_back的時候,如果空間不足,會自動增補一些空間,如果沒有預留的空間可用
就直接申請另一塊可用的連續的空間,把數據拷貝過去,然后刪除舊空間,使用新空間
結果造成效率低下 。
可以通過以下兩種組合來防止reallocate.
-
vector::resize() 使用array index,效率最高,但是需要提前知道size大小
-
vector::reserve()使用 push_back(),效率一般,較原生有一定提升。