這個blog來源於一個朋友提出的的問題
下面的代碼想輸出0-9,可不行。原因是iterStart居然等於iterEnd,為什嗎?
list<int> li;
vector<int> vi;
for(int c=0;c<10;c++) li.push_back(c);
vi.reserve(li.size());
copy(li.begin(),li.end(),vi.begin());
vector<int>::iterator iterStart=vi.begin();
vector<int>::iterator iterEnd=vi.end();
vector<int>::iterator it=iterStart;
for(;it!=iterEnd;it++)
{
cout<<*it<<endl;
}
---------------------------------------------------------
有趣的問題,2種解決方案:
1)把
vi.reserve(li.size());
修改為
vi.resize(li.size());
2)在構造時指定空間
vector<int> vi(li.size())
問題在於對reserve()函數的理解:
下面是reserve()的MSDN協助:
vector::reserve
void reserve(size_type n);
The member function ensures that capacity() henceforth returns at least n.
下面是resize()的MSDN協助:
vector::resize
void resize(size_type n, T x = T());
The member function ensures that size() henceforth returns n. If it
must lengthen the controlled sequence, it appends elements with value x.
關鍵在於:reserve()已經分配了空間,但是“不可以使用”!考慮以下的使用情境:
Step1:現在大小是10(size()和capacity()返回10),保留1000個元素的空間(使用reserve()),說明以後1000個元素的空間已經分配成功了,但是size()仍然返回10,capacity()返回1000!
Step2:調用resize(100),實際沒有重新分配空間(因為已經“分配並保留”了1000)。此時size()返回100, capacity()返回1000!
A little deeper:查看STL的原始碼會更容易的理解這個問題。列出vector的size()和capacity()函數的實現:
size_type size() const
{return (_First == 0 ? 0 : _Last - _First); }
size_type capacity() const
{return (_First == 0 ? 0 : _End - _First); }
注意:size()使用了_Last指標,而capacity()使用了_End指標!
Aha!原來所謂的“尾指標”有2個:
_Last表示真正的資料(允許使用的空間)的尾指標;
_End表示已經分配的空間的尾指標;
這個問題的根本還是對於STL容器的記憶體配置方式的理解,i.e.
reserve()和resize()的區別。如果沒有提供reserve()方法,相信會更加容易理解,代價是失去了更好的記憶體管理的手段。提供
reserve()方法的目的,我理解是允許使用者使用memory
pool的思想來手動控制記憶體的分配,即預先保留足夠多的空間(由_End控制),然後根據需要使用實際的記憶體空間(由_Last控制)