std::vector
- vector
- インクルード
- 初期化(コンストラクタ)
- 要素アクセス([],at,front,back,begin,end,rbegin,rend)
- 領域確保(resize,reserve)
- サイズ確認(size,capacity,max_size,empty)
- 編集(push_back,pop_back,assign,insert,erase,clear,swap)
- 従来の配列との互換性
- 多次元配列
- erase,clear後のメモリサイズ
vector†
ランダムアクセス配列.
要素は連続したメモリ領域に確保される(シーケンスコンテナ)ため,
イテレータでのアクセスだけでなく,従来のポインタを用いた要素アクセスも可能.
さらに,動的配列であり,そのサイズを容易に変更可能.
ただし,処理中にさらに要素を拡大されることを見越して,サイズ変更時に通常の配列よりも多めのメモリを確保してしまうため,
巨大で大きさが固定の領域を確保したい場合は通常の配列を用いた方がよいかもしれない.
C++のnewを用いた場合と異なり,deleteの必要はない.vector変数の有効なスコープを抜けた時点でクリアされる.
インクルード†
#include <vector>
初期化(コンストラクタ)†
explicit vector(const Allocator& = Allocator());
explicit vector(size_type n, const T& value= T(), const Allocator& = Allocator());
template <class InputIterator>
vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
vector(const vector<T,Allocator>& x);
使用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| | #include <iostream>
#include <vector>
using namespace std;
template<class T>
inline void output(vector<T> x)
{
vector<T>::iterator iter;
for(iter = x.begin(); iter != x.end(); ++iter){
cout << *iter << " ";
}
cout << endl;
}
int main(void)
{
vector<int> a; vector<int> b(5); vector<int> c(5, 3); vector<int> d(c.begin(), c.end()); vector<int> e(d);
a.resize(5, 1);
output(a);
output(b);
output(c);
output(d);
output(e);
return 0;
}
|
実行結果
1 1 1 1 1
0 0 0 0 0
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
要素アクセス([],at,front,back,begin,end,rbegin,rend)†
- [] : 通常の配列と同じオペレータ[]を用いたアクセス
reference operator[](size_type n);
const_reference operator[](size_type n) const;
- at() : 範囲外アクセス時にout_of_range例外を投げる関数
const_reference at(size_type n) const;
reference at(size_type n);
- front() : コンテナの最初の要素にアクセスする関数
reference front();
const_reference front() const;
- back() : コンテナの最後の要素にアクセスする関数
reference back();
const_reference back() const;
領域確保(resize,reserve)†
サイズ確認(size,capacity,max_size,empty)†
編集(push_back,pop_back,assign,insert,erase,clear,swap)†
- assign(n, val) :
template <class InputIterator>
void assign(InputIterator first, InputIterator last);
void assign(size_type n, const T& u);
使用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| | #include <iostream>
#include <vector>
using namespace std;
int main(void)
{
vector<double> x0(5), x;
x.assign(5, 1);
output(x);
double y = 1.0;
vector<double>::iterator iter;
for(iter = x0.begin(); iter != x0.end(); ++iter){
*iter = y;
y *= 1.5;
}
output(x0);
x.assign(x0.begin()+1, x0.end()-1);
output(x);
double x2[] = {10.0, 11.0, 12.0};
x.assign(x2, x2+3);
output(x);
return 0;
}
|
実行結果
1 1 1 1 1
1 1.5 2.25 3.375 5.0625
1.5 2.25 3.375
10 11 12
- insert() : イテレータで示された位置に要素を挿入する.
iterator insert(iterator position, const T& val);
void insert(iterator position, size_type n, const T& val);
template <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last);
使用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| | #include <iostream>
#include <vector>
using namespace std;
int main(void)
{
vector<double> x(4, 0.0);
vector<double> y(3, 3.0);
output(x);
int capa0 = x.capacity();
vector<double>::iterator iter = x.begin();
iter = x.insert(iter+2, 1.0); output(x);
x.insert(iter+1, 2, 2.0);
output(x);
if(capa0 != x.capacity()){
iter = x.begin()+2;
}
x.insert(iter+3, y.begin(), y.end());
output(x);
int z[] = { 4, 4, 4, 4 };
x.insert(x.begin()+7, z, z+4);
output(x);
return 0;
}
|
実行結果
0 0 0 0
0 0 1 0 0
0 0 1 2 2 0 0
0 0 1 2 2 3 3 3 0 0
0 0 1 2 2 3 3 4 4 4 4 3 0 0
- erase(iter) : イテレータで示された位置の要素を削除する.
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
- clear() : コンテナのクリア.全要素を削除する.
void clear();
使用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| | #include <iostream>
#include <vector>
using namespace std;
int main(void)
{
vector<int> x(5);
for(int i = 0; i < (int)x.size(); ++i) x[i] = i;
output(x);
cout << "(" << x.size() << ")" << endl;
x.erase(x.begin()+1);
output(x);
cout << "(" << x.size() << ")" << endl;
x.erase(x.begin()+2, x.end());
output(x);
cout << "(" << x.size() << ")" << endl;
x.clear();
cout << "(" << x.size() << ")" << endl;
return 0;
}
|
実行結果
0 1 2 3 4
(5)
0 2 3 4
(4)
0 2
(2)
(0)
従来の配列との互換性†
vectorは要素がメモリ上にシークエンスに並んでいるので,
従来の配列と互換性を持つ.
1
2
3
4
5
6
7
| | vector<int> x;
for(int i = 0; i < 5; ++i) x.push_back(i);
int *p = &x[0];
p[1] = 3;
for(int i = 0; i < 5; ++i) cout << p[i] << " ";
cout << endl;
|
上記のように最初の要素のポインタを用いて配列のように扱える.
ただし,resizeやinsertなどでサイズ変更があった場合,
サイズ変更前のポインタやイテレータが有効であることは保証されないので注意.
多次元配列†
vectorで多次元配列を作成したい場合,以下のように定義する(2次元の場合).
vector< vector<int> > x;
定義時に容量を確保し,初期化したい場合は,
vector< vector<int> > x(n, vector<int>(n, 0));
上記の例ではn×nのサイズを確保し,0で初期化している.
resize関数を用いる場合も同様で,
x.resize(n, vector<int>(n, 0));
となる.
使用する場合は普通の2次元配列と同様に
x[i][j]
として使用する.
erase,clear後のメモリサイズ†
STLのコンテナでは,eraseやclear関数で要素を削除しても,
確保されたメモリはスコープを抜けるまでは確保されたままである.
例えば,以下のようなコードを実行すると,
1
2
3
4
5
6
7
| | vector<int> x;
x.resize(100);
for(int i = 0; i < 100; ++i) x[i] = i;
cout << x.capacity() << endl;
x.clear();
cout << x.capacity() << endl;
|
結果は,
100
100
となり,clearを実行した後もメモリが確保されたままであることが分かる.
これを防ぐ方法としてswapを用いる方法と,shrink_to_fit関数を用いる方法がある.
swapの場合は以下のようにする.
vector<int>(x).swap(x);
shrink_to_fitの場合は単純に
x.shrink_to_fit();
shrink_to_fitは環境によっては使えないかもしれないので注意(Visual Studio 2010では大丈夫).
試しに先ほどのコードに
x.shrink_to_fit();
cout << x.capacity() << endl;
と追記して実行してみると,
100
100
0
となる.
|