vector
vector就是動態數組.它也是在堆中分配內存,元素連續存放,有保留內存,如果減少大小后,內存也不會釋放.如果新值>當前大小時才會再分配內存.
它擁有一段連續的內存空間,並且起始地址不變,因此它能非常好的支持隨即存取,即[]操作符,但由於它的內存空間是連續的,所以在中間進行插入和刪除會造成內存塊的拷貝,另外,當該數組后的內存空間不夠時,需要重新申請一塊足夠大的內存並進行內存的拷貝。這些都大大影響了vector的效率。
對最后元素操作最快(在后面添加刪除最快 ), 此時一般不需要移動內存,只有保留內存不夠時才需要
對中間和開始處進行添加刪除元素操作需要移動內存,如果你的元素是結構或是類,那么移動的同時還會進行構造和析構操作,所以性能不高 (最好將結構或類的指針放入vector中,而不是結構或類本身,這樣可以避免移動時的構造與析構)。
訪問方面,對任何元素的訪問都是O(1),也就是是常數的,所以vector常用來保存需要經常進行隨機訪問的內容,並且不需要經常對中間元素進行添加刪除操作.
相比較可以看到vector的屬性與string差不多,同樣可以使用capacity看當前保留的內存,使用swap來減少它使用的內存.
capacity()返回vector所能容納的元素數量
例如下面的代碼
#include <iostream>
#include <vector>
using namespace std;
class A{
char *p;
public: A();
~A();
};
template<typename T>
int traverse(vector<T> vecData){
typename vector<T>::iterator it;
int i=0;
//for(T::size_type i=0;it!=vecData.end();it++,i++)
for (it = vecData.begin(); it != vecData.end(); ++it)
cout<<"\t"<<i<<"\t"<<*it<<endl;
}
A::A(){p=(char *)malloc(sizeof(char) * 1024);}
A::~A(){free(p);}
int f();
int main(){f();}
int f(){
A o;
vector<string> vecData;
vector<char*> vecPtr;
char *a=(char *)malloc(sizeof(char) * 1024);
a[0]='o';
a[1]='k';
a[3]='\0';
string data="1234";
vecData.push_back(data);
cout<<"vecData[0]\t"<<vecData[0]<<"\tcapacity:\t"<<vecData.capacity()<<endl;
data.clear();
data="4321";
vecData.push_back(data);
cout<<"vecData[1]\t"<<vecData[1]<<"\tcapacity:\t"<<vecData.capacity()<<endl;
data.clear();
std::sort(vecData.begin(),vecData.end());
traverse(vecData);
vecPtr.push_back(a);
cout<<"before ptr vector release"<<endl;
traverse(vecPtr);
free(a);
a=NULL;
cout<<"after ptr vector release"<<endl;
traverse(vecPtr);
}
此時運行valgrind:
(1)不會出現vecData內存未釋放的情況,說明vector對象析構函數在退出的時候自動進行了調用;
(2)不會出現因為刪除掉data就導致讀不到vector中內容的情況,說明在push_back增加元素的時候進行了拷貝操作,即使是原有數據刪除也不會影響;
(3)當vector中的元素為指針的時候,拷貝的是指針本身,而不是指針指向的對象,此時釋放掉指針對象的空間,那么vector中的元素就找不到地址,用valgrind會告訴說訪問已經free的內存,但是不會出現內存泄露;
==14367== Invalid read of size 1 ==14367== at 0x3B7726CF1A: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so) ==14367== by 0x3B7726234A: fwrite (in /lib64/libc-2.5.so) ==14367== by 0x3E95690310: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib64/libstdc++.so.6.0.8) ==14367== by 0x403D9D: int traverse<char*>(std::vector<char*, std::allocator<char*> >) (testVector.cpp:33) ==14367== by 0x4013FA: f() (testVector.cpp:64) ==14367== by 0x4014FA: main (testVector.cpp:38) ==14367== Address 0x4e24481 is 1 bytes inside a block of size 1,024 free'd ==14367== at 0x4A05D21: free (vg_replace_malloc.c:325) ==14367== by 0x401374: f() (testVector.cpp:60) ==14367== by 0x4014FA: main (testVector.cpp:38) ==14367== 0 ok ==14367== ==14367== HEAP SUMMARY: ==14367== in use at exit: 0 bytes in 0 blocks ==14367== total heap usage: 12 allocs, 13 frees, 2,220 bytes allocated ==14367== ==14367== All heap blocks were freed -- no leaks are possible ==14367== ==14367== For counts of detected and suppressed errors, rerun with: -v ==14367== Use --track-origins=yes to see where uninitialised values come from ==14367== ERROR SUMMARY: 9 errors from 8 contexts (suppressed: 4 from 4)
