1. 程式人生 > >C++筆記 -- 序列容器vector

C++筆記 -- 序列容器vector

向量(vector)
向量(vector)是表示可以改變大小的陣列的序列容器。

就像陣列一樣,向量使用連續的儲存位置作為元素,這意味著它們的元素也可以使用常量指向其元素的偏移來訪問,並且與陣列一樣有效。但與陣列不同是向量的大小可以動態變化,其儲存由容器自動處理。

在內部,向量使用動態分配的陣列來儲存它們的元素。可能需要重新分配此陣列,以便在插入新元素時增大大小,這意味著分配新陣列並將所有元素移動到該陣列。就處理時間而言,這是相對昂貴的任務,因此,每次將元素新增到容器時,向量都不會重新分配。

相反,向量容器可以分配一些額外的儲存空間以適應可能的增長,因此容器的實際容量可能大於包含其元素所需的儲存容量(即,其大小)。庫可以實現不同的增長策略以在記憶體使用和重新分配之間取得平衡,但無論如何,重新分配只應以對數增長的大小間隔發生,以便在向量末尾插入單個元素可以提供攤銷的常量時間複雜性(見push_back)。

因此,與陣列相比,向量消耗更多記憶體,以換取管理儲存和以有效方式動態增長的能力。

與其他動態序列容器(deques,lists和forward_lists)相比,向量非常有效地訪問其元素(就像陣列一樣)並且相對有效地從其末尾新增或刪除元素。對於涉及在末尾以外的位置插入或刪除元素的操作,它們的效能比其他位置差,並且與列表和forward_lists相比具有更少的一致的迭代器和引用。


容器屬性
1. 序列
序列容器中的元素按嚴格的線性順序排序。 各個元素按其順序訪問它們的位置。
2. 動態陣列
允許直接訪問序列中的任何元素,甚至通過指標算術,並在序列的末尾提供相對快速的元素新增/刪除。
3. 分配器
容器使用allocator物件來動態處理其儲存需求。


建構函式:
C++11中vector的建構函式有如下:
1. default
explicit vector (const allocator_type& alloc = allocator_type());
2. fill
explicit vector (size_type n);
vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type());
3. range
template <class InputIterator>
vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
4. copy
vector (const vector& x);
vector (const vector& x, const allocator_type& alloc);
5. move
vector (vector&& x);
vector (vector&& x, const allocator_type& alloc);
6. initializer list
vector (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());

// constructing vectors
#include <iostream>
#include <vector>

int main ()
{
	using namespace std;
	// constructors
	vector<int> one;                                // empty vector of ints
	vector<int> two (4, 10);                       // 4 ints with value 10
	vector<int> three (two.begin(), two.end());  // iterating through two
	vector<int> four(three);                       // a copy of three

	// construct from arrays:
	int myarray[] = {1, 2, 3, 4, 5};
	vector<int> five (myarray, myarray + sizeof(myarray) / sizeof(int) );

	cout << "contents of five are:";
	for (vector<int>::iterator it = five.begin(); it != five.end(); ++it)
	{
		cout << ' ' << *it;
	}
	cout << endl;

  return 0;
}

Iterators:
begin
將迭代器返回到開頭(公共成員函式)
end
將迭代器返回到end(公共成員函式)
rbegin
返回反向迭代器以反向開始(公共成員函式)
rend
將反向迭代器返回到反向結束(公共成員函式)
cbegin
將const_iterator返回到開頭(公共成員函式)C++11
cend
將const_iterator返回到end(公共成員函式)C++11
crbegin
返回const_reverse_iterator以反向開始(公共成員函式)C++11
crend
將const_reverse_iterator返回到反向結束(公共成員函式)C++11

//Iterators:
// vector::begin/end
// vector::rbegin/rend
// vector::cbegin/cend
// vector::crbegin/crend

#include <iostream>
#include <vector>

int main ()
{
	using namespace std;
	vector<int> vec = {1, 2, 3, 4, 5};

	for(auto it=vec.cbegin(); it != vec.cend(); ++it)
	{
		cout << " " << *it;
	}
	cout << endl;

	for(auto it=vec.crbegin(); it != vec.crend(); ++it)
	{
		cout << " " << *it;
	}
	cout << endl;

	
	for(auto it=vec.begin(); it != vec.end(); ++it)
	{
		cout << " " << *it;
		*it *= 2;
	}
	cout << endl;

	for(auto it=vec.rbegin(); it != vec.rend(); ++it)
	{
		cout << " " << *it;
	}
	cout << endl;
	
	return 0;
}

Capacity:
size
返回大小(公共成員函式)
max_size
返回最大大小(公共成員函式)
resize
更改大小(公共成員函式)
capacity
返回已分配儲存容量的大小(公共成員函式)
empty
返回vector是否為空(公共成員函式)
reverse
請求更改容量(公共成員函式)
shrink_to_fit
縮小到適合的大小(公共成員函式)C++11

//Capacity:
// vector::capacity
// vector::reserve
// vector::resize
// vector::shrink_to_fit
// vector::size
// vector::empty
#include <iostream>
#include <vector>

int main ()
{
	using namespace std;
	int sz;
	vector<int> foo;
	
	/*
	size_type capacity() const noexcept;
	*/
	sz = foo.capacity();
	cout << "making foo grow:\n";
	for (int i=0; i<100; ++i) 
	{
		foo.push_back(i);
		if (sz!=foo.capacity()) 
		{
			sz = foo.capacity();
			cout << "i=" << i << ", capacity changed: " << sz << endl;
    	}
	}

	vector<int> vec(100);
	cout << "1. capacity of vec: " << vec.capacity() << endl;
	/*
	void resize (size_type n);
	void resize (size_type n, const value_type& val);
	*/
	vec.resize(10);
	cout << "2. capacity of vec: " << vec.capacity() << endl;
	//size_type size() const noexcept;
	cout << "2. size of vec: " << vec.size() << endl;
	//size_type max_size() const noexcept;
	cout << "2. max_size of vec: " << vec.max_size() << endl; 
	
	//void shrink_to_fit();
	vec.shrink_to_fit();
	cout << "3. capacity of vec: " << vec.capacity() << endl;

	//void reserve (size_type n);
	vec.reserve(300);
	cout << "4. capacity of vec: " << vec.capacity() << endl;

	vec.clear();
	//bool empty() const noexcept;
	if(vec.empty())
	{
		cout << "5. current vec is empty" << endl;
	}
	
	return 0;
}

Element access:
operator[]
訪問元素(公共成員函式)
at
訪問元素(公共成員函式)
front
訪問第一個元素(公共成員函式)
back
訪問最後一個元素(公共成員函式)
data
訪問資料(公共成員函式)

//Element access:
// vector::operator[]
// vector::data
// vector::at
// vector::front
// vector::back
#include <iostream>
#include <vector>

int main ()
{
	using namespace std;
	vector<int> vec(5);

	//vector::operator[]
	for(int i=0; i<vec.size(); ++i)
	{
		vec[i] = i;
	}
	for(auto& x: vec)
	{
		cout << " " << x;
	}
	cout << endl;

	//vector::data
	int* p = vec.data();
	*p = 10;
	++p;
	*p = 20;
	++p;
	*p = 30;
	p[2] = 40; //means vec[2+2] = 40;

	//vector::at
	for(int i=0; i<vec.size(); ++i)
	{
		cout << ' ' << vec.at(i);
	}
	cout << endl;

	vec.push_back(100);
	//vector::front , vector::back
	vec.front() = vec.back() - 50;
	cout << "vec.front()=" << vec.front() << endl;
	cout << "vec.back()=" << vec.back() << endl;

	return 0;
}

Modifiers:
assign
分配向量內容(公共成員函式)
push_back
在最後新增元素(公共成員函式)
pop_back
刪除最後一個元素(公共成員函式)
insert
插入元素(公共成員函式)
erase
擦除元素(公共成員函式)
swap
交換內容(公共成員函式)
clear
清除內容(公共成員函式)
emplace
構造並插入元素(公共成員函式) C++11
emplace_back
構造並在最後插入元素(公共成員函式)C++11

//Modifiers:
// vector::assign
// vector::push_back
// vector::pop_back
// vector::emplace/emplace_back
// vector::erase
// vector::empty
// vector::clear
// vector::swap
// vector::insert
#include <iostream>
#include <vector>

int main ()
{
	using namespace std;
	
	vector<int> one;
	vector<int> two;
		
	//void assign (size_type n, const value_type& val);
	one.assign(10, 100);	// 10 ints with a value of 100
	cout << "Size of one: " << one.size() << endl;
	cout << "Value of one: ";
	for(auto& value: one)
	{
		cout << " " << value;
	}
	cout << endl;

	/*
	template <class InputIterator>
	void assign (InputIterator first, InputIterator last);
	*/
	two.assign(one.begin()+1, one.end()-1);	// the 8 central values of one

	//void push_back (const value_type& val);
	two.push_back(789);
	cout << "Value of two: ";
	for(auto& value: two)
	{
		cout << " " << value;
	}
	cout << endl;

	//void pop_back();
	two.pop_back();
	cout << "Size of two: " << two.size() << endl;

		
	vector<int> vec = {10,20,30};
	/*
	template <class... Args>
	iterator emplace (const_iterator position, Args&&... args);
	*/
	auto it = vec.emplace ( vec.begin()+1, 100 );
	vec.emplace ( it, 200 );
	vec.emplace ( vec.end(), 300 );

	/*
	template <class... Args>
  	void emplace_back (Args&&... args);
	*/
	vec.emplace_back(400);
	vec.emplace_back(500);

	cout << "vec contains:";
	for (auto& x: vec)
	{
		cout << ' ' << x;
	}	
	cout << endl;

	//iterator erase (const_iterator position);
	vec.erase(vec.begin()+2);
	cout << "vec contains:";
	for (auto& x: vec)
	{
		cout << ' ' << x;
	}	
	cout << endl;

	//iterator erase (const_iterator first, const_iterator last);
	vec.erase(vec.begin()+1, vec.end()-2);
	cout << "vec contains:";
	for (auto& x: vec)
	{
		cout << ' ' << x;
	}	
	cout << endl;
	
	//void swap (vector& x);
	vec.swap(two);

	//void clear() noexcept;
	vec.clear();

	//bool empty() const noexcept;
	if(vec.empty())
	{
		//iterator insert (const_iterator position, const value_type& val);
		vec.insert(vec.begin(), 123);
	}
	
	cout << "vec contains:";
	for (auto& x: vec)
	{
		cout << ' ' << x;
	}	
	cout << endl;

	return 0;
}

Allocator:
get_allocator
獲取分配器(公共成員函式)

//Allocator:
// vector::get_allocator
//template <class T> class allocator;

#include <iostream>
#include <vector>

int main ()
{
	using namespace std;
	
	vector<int> vec;
	int * p;
	unsigned int i;
	
	// Allocate block of storage for 5 elements:
	p = vec.get_allocator().allocate(5);

	// Construct objects:
	for (i=0; i<5; i++) 
	{
		vec.get_allocator().construct(&p[i], (i+1)*10);
	}

	cout << "allocated array:";
	for (i=0; i<5; i++)
	{
		cout << ' ' << p[i];
	}
	cout << endl;

	// Destroy objects:
	for (i=0; i<5; i++)
	{
		vec.get_allocator().destroy(&p[i]);
	}
	//Release block of storage
	vec.get_allocator().deallocate(p,5);

	return 0;
}