什麼是數組? 簡單來講數組表明一塊連續的內存,內部包含連續的一排相同的對象, 由於內存分佈連續且對象大小相同,因此咱們能夠高效的根據索引隨機訪問和賦值。
數組是咱們平時用的最多的數據結構, 由於它很符合咱們程序運行時的平坦內存佈局,使用起來簡單而高效。能夠這樣說,只要恰當的使用,數組能夠知足咱們工做中的大部分須要。
數組包括靜態數組和動態數組, C/C++語言內置支持數組, 咱們平時通常這樣用:
void
test()
{
int
ar[
5
]
=
{
1
,
2
,
3
,
4
,
5
};
int
v
=
a[
2
];
int
*
pAr
=
new
int
[
3
];
pAr[
1
]
=
v;
delete []pAar;
}
上面咱們討論的動態數組是C++語言內置支持的, 可是由於內置數組大小固定且容易越界, 另外還有上面的多態問題, C++標準庫爲咱們提供了另外一種封裝vector, 咱們能夠這樣用:
void
test()
{
vector
<
int
>
ar;
ar.push_back(
1
);
ar.push_back(
2
);
int
d
=
ar[
1
];
ar[
2
]
=
10
;
}
咱們能夠看到, vector使用起來很是方便, 一方面咱們能夠像內置數組同樣使用, 另外一方面咱們不用再擔憂容量問題, 由於它會在大小不夠時自動增長。
vector雖然簡單,可是實際上它有 很多陷井和技巧, 下面列舉一些常見問題:
1。當心迭代器失效
void
test()
{
vector
<
int
>
ar;
ar.push_back(
1
);
vector
<
int
>
::iterator itr
=
ar.begin();
for
(
int
i
=
0
; i
<
100
;
++
i)
{
ar.push_back(i);
}
int
d
=
*
itr;
}
你看出上面代碼的問題了嗎?
不錯, 可能在咱們push_back過程當中, 內存從新分配了, 致使咱們原先記錄的迭代器itr已經失效, 後面再從新訪問就出錯了。
2。防止內存
屢次
分配
咱們知道在push_back過程當中, 當數組容量不夠時, 咱們就會從新分配內存, 而後將已有的元素進行拷貝, 效率很低。
因此最好的方法是用reserve()方法對須要的大小進行正確的估計,而後預留足夠的空間, 防止從新內存分配。
3。釋放已分配空間
有些時候某個vector對象已經分配了挺大空間,當用的差很少時, 咱們須要釋放這些空間, 可是要保留該對象,要怎麼作?
這裏有個挺實用的swap技巧:
vector
<
int
>
vec;
void
test()
{
for
(
int
i
=
0
; i
<
10000
;
++
i)
vec.push_back(i);
vector
<
int
>
temp;
vec.swap(temp);
}
4。刪除某些符合條件的元素
void
test()
{
vector
<
int
>
ar;
for
(
int
i
=
0
; i
<
100
;
++
i)
{
ar.push_back(i);
}
vector
<
int
>
::iterator itr
=
ar.begin();
for
(;itr
!=
ar.end();)
{
if
(
*
itr
>
10
)
{
itr
=
ar.erase(itr);
}
else
{
++
itr;
}
}
}
上面的代碼刪除數組中大於10的全部item, 實際上咱們能夠下面更簡單的方法替代:
ar.erase(remove_if(ar.begin(), ar.end(), bind2nd(greater
<
int
>
(),
10
)), ar.end());
從上面的一些技巧,咱們能夠看到, 只有真正理解了vector的內部實現原理, 咱們才能規避一些使用陷井, 更簡單而高效的開發程序。
上面咱們討論的vector主要針對的模擬C++內置的動態數組部分, 而對於靜態數組部分,咱們是否是也有相應的類?
是的,C++11裏新增的array就是作這個事的, 咱們能夠這樣用:
void
test()
{
std::array
<
int
,
10
>
ar
=
{
1
,
2
,
3
,
4
};
ar[
5
]
=
33
;
}
其中array<int, 10>在內部存儲其實是int data[10];
最後, 簡單總結下,咱們從C++的內置數組講到標準庫提供的vector, 最後談到C++11新增的array, 數組這個最基本的數據結構在C++中終於有了完整的支持。