cpp►STL容器->序列容器->vector

std::vector是一个动态数组容器,提供数组的特性并支持动态增长。它可以容纳任意类型的元素,通过元素在序列中的位置进行访问。std::vector提供了构造函数、赋值运算符、迭代器、容量管理、元素访问、修改和分配器等功能。它使用动态分配的数组,当需要更多空间时会自动扩展,但这个过程可能涉及元素的复制和新数组的分配,可能有性能开销。此外,std::vector还支持非成员函数如swap和比较运算符,以及针对bool类型的特殊化std::vector<bool>,该特殊化提供了位操作和效率优化。

描述

std::vector
template <class T, class Alloc = allocator<T>> class vector;
vector是序列容器,代表数组可以改变大小。

就像数组,vector使用连续的存储位置的元素,这意味着它们的元素也可以像数组一样通过在常规指针上使用偏移量(ptr+offsetN)来访问元素。但与数组不同的是,它们的大小可以动态地改变,这由它们的存储容器自动处理。

在内部,vector使用动态分配的数组来存储它们的元素。这个数组可能需要重新分配,插入新元素时size变大,这意味着分配一个新数组并移动所有元素到这个新数组。这是一个相对昂贵的任务的处理时间,因此,当添加一个新元素时,vector不重新分配空间。

相反,vector容器可能会分配一些额外的存储空间来容纳可能的元素增加,因此容器有可能实际容量大于实际元素所占的大小。为应对元素增加,库可以实现不同的策略来平衡内存使用和重新分配,但在任何情况下,重新分配应该只发生在元素以对数增长时,以便插入单个元素的vector可以提供恒定分摊时间复杂度。

因此,相比数组,vector使用更多的内存,以换取能够高效地管理内存和元素的动态增长。

相比其他动态序列容器(deques、list和forward_lists),vector访问它的元素是非常有效的(就像数组)和相对有效的从末尾添加或删除元素。如果不是在末尾,插入或删除元素,它们比其他容器表现更差,并且相比lists和forward_lists,vector有较少的格式统一的迭代器和引用。

容器属性(Container properties)
  • Sequence
    序列容器中的元素是按严格的线性序列排序的。通过元素在这个序列中的位置去访问单个元素。
  • Dynamic array
    允许直接访问序列中的任何元素,甚至通过指针算法,并提供了从元素末尾相对快速地添加/删除元素。
  • Allocator-aware
    容器使用一个分配器对象动态地处理它的存储需求。
模板参数(Template parameters)
  • T
    元素的类型。
    只有当T在移动时确保它不会抛出异常,它的实现在移动元素时才能得到优化处理而不是在重新分配时复制它们。
    别名是成员类型vector::value_type。
  • Alloc
    分配器对象的类型用于定义存储分配模型。默认情况下,使用类模板allocator<T>,它定义了简单的内存分配模型,并且是与值无关的。
    别名是成员类型vector::allocator_type。
成员类型(Member types)
成员类型定义描述
value_type第一个模板参数T
allocator_type第二个模板参数Alloc默认为allocator<value_type>
referencevalue_type&
const_referenceconst value_type&
pointerallocator_traits<allocator_type>::pointer对于默认的allocator而言,就是value_type*
const_pointerallocator_traits<allocator_type>::const_pointer对于默认的allocator而言,就是const value_type*
iterator对value_type的随机访问迭代器
const_iterator对const value_type的随机访问迭代器
reverse_iteratorreverse_iterator<iterator>
const_reverse_iteratorreverse_iterator<const_iterator>
difference_type一个有符号整型,等同于iterator_traits<iterator>::difference_type通常与ptrdiff_t是相同的
size_type一个无符号整型,它能表示任何difference_type的非负值通常与size_t是相同的
成员函数(Member functions)
  • 构造函数:
default(1) explicit vector(const allocator_type& alloc = allocator_type());
fill(2)    explicit vector(size_type n, const value_type& val = value_type(),
                           const allocator_type& alloc = allocator_type());
range(3)   template <class InputIterator>
		   vector(InputIterator first, InputInterator last, 
		          const allocator_type& alloc = allocator_type();
copy(4)    vector(const vector& x);
// constructing vectors
#include <iostream>
#include <vector>
int main() {
	// constructors used in the same order as described above:
	std::vector<int> first;// empty vector of ints
	std::vector<int> second(4, 100);// four ints with value 100
	std::vector<int> third(second.begin(), second.end());// iterating through second
	std::vector<int> fourth(third);// a copy of third

	// the iterator constructor can also be used to construct from arrays:
	int myints[] = { 16,2,77,29 };
	std::vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));

	std::cout << "The contents of fifth are:";
	for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';
	return 0;
}
The contents of fifth are: 16 2 77 29
  • 析构函数:
    ~vector();
    销毁容器的所有元素,并使用容器的allocator取消vector分配的存储容量(capacity)。
  • 赋值运算符:
    std::vector::operator=
// vector assignment
#include <iostream>
#include <vector>
int main() {
	std::vector<int> foo(3, 0);
	std::vector<int> bar(5, 0);

	bar = foo;
	foo = std::vector<int>();

	std::cout << "Size of foo:" << int(foo.size()) << '\n';
	std::cout << "Size of bar:" << int(bar.size());
	return 0;
}
Size of foo:0
Size of bar:3
迭代器(Iterators)
  • begin、end、rbegin、rend
// vector::rbegin/rend
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector(5);  // 5 default-constructed ints
	int i = 0;
	std::vector<int>::reverse_iterator rit = myvector.rbegin();
	for (; rit != myvector.rend(); ++rit)
		*rit = ++i;
	std::cout << "myvector contains:";
	for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';
	return 0;
}
myvector contains: 5 4 3 2 1
  • cbegin、cend
// vector::cbegin/cend
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector = { 10,20,30,40,50 };
	std::cout << "myvector contains:";
	for (std::vector<int>::const_iterator it = myvector.cbegin(); it != myvector.cend(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';
	return 0;
}
myvector contains: 10 20 30 40 50
  • crbegin、crend
// vector::crbegin/crend
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector = { 1,2,3,4,5 };
	std::cout << "myvector backwards:";
	for (std::vector<int>::const_reverse_iterator rit = myvector.crbegin(); rit != myvector.crend(); ++rit)
		std::cout << ' ' << *rit;
	std::cout << '\n';
	return 0;
}
myvector backwards: 5 4 3 2 1
容量(Capacity)
  • size、max_size、capacity
// comparing size, capacity and max_size
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	// set some content in the vector:
	for (int i = 0; i < 100; i++) 
		myvector.push_back(i);
	std::cout << "size: " << myvector.size() << "\n";
	std::cout << "capacity: " << myvector.capacity() << "\n";
	std::cout << "max_size: " << myvector.max_size() << "\n";
	return 0;
}
size: 100
capacity: 128
max_size: 1073741823
  • empty
// vector::empty
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	int sum(0);
	for (int i = 1; i <= 10; i++) 
		myvector.push_back(i);
	while (!myvector.empty()) {
		sum += myvector.back();
		myvector.pop_back();
	}
	std::cout << "total: " << sum << '\n';
	return 0;
}
total: 55
  • resize
    void resize(size_type n);
    void resize(size_type n, const value_type& val);
    重设容器大小(size)以使其包含n个元素。
// resizing vector
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	// set some initial content:
	for (int i = 1; i < 10; i++) 
		myvector.push_back(i);
	myvector.resize(5);// n < current size
	myvector.resize(8, 100);// n > current size,with a value
	myvector.resize(12);// n > current size,with value-initialized
	std::cout << "myvector contains:";
	for (int i = 0; i < myvector.size(); i++)
		std::cout << ' ' << myvector[i];
	std::cout << '\n';
	return 0;
}
myvector contains: 1 2 3 4 5 100 100 100 0 0 0 0
  • reserve
    void reserve(size_type n);
    请求vector容量(capacity)至少足以包含n个元素。
// vector::reserve
#include <iostream>
#include <vector>
int main() {
	std::vector<int>::size_type sz;
	std::vector<int> foo;
	sz = foo.capacity();
	std::cout << "making foo grow:\n";
	for (int i = 0; i < 100; ++i) {
		foo.push_back(i);
		if (sz != foo.capacity()) {
			sz = foo.capacity();
			std::cout << "capacity changed: " << sz << '\n';
		}
	}
	std::vector<int> bar;
	sz = bar.capacity();
	bar.reserve(100);// Request a change in capacity(this is the only difference with foo above)
	std::cout << "making bar grow:\n";
	for (int i = 0; i < 100; ++i) {
		bar.push_back(i);
		if (sz != bar.capacity()) {
			sz = bar.capacity();
			std::cout << "capacity changed: " << sz << '\n';
		}
	}
	return 0;
}
making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 4
capacity changed: 8
capacity changed: 16
capacity changed: 32
capacity changed: 64
capacity changed: 128
making bar grow:
capacity changed: 100
  • shrink_to_fit
    void shrink_to_fit();
    请求容器减少(shrink)容量(capacity)去适应它的size大小。
// vector::shrink_to_fit
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector(100);
	std::cout << "1. capacity of myvector: " << myvector.capacity() << '\n';

	myvector.resize(10);
	std::cout << "2. capacity of myvector: " << myvector.capacity() << '\n';

	myvector.shrink_to_fit();
	std::cout << "3. capacity of myvector: " << myvector.capacity() << '\n';
	return 0;
}
1. capacity of myvector: 100
2. capacity of myvector: 100
3. capacity of myvector: 10
访问元素(Element access)
  • operator[]
  • at
// vector::at
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector(10);// 10 zero-initialized ints
	// assign some values:
	for (unsigned i = 0; i < myvector.size(); i++)
		myvector.at(i) = i;
	std::cout << "myvector contains:";
	for (unsigned i = 0; i < myvector.size(); i++)
		std::cout << ' ' << myvector.at(i);
	std::cout << '\n';
	return 0;
}
myvector contains: 0 1 2 3 4 5 6 7 8 9
  • front、back
    reference front(); 返回一个指向vector首元素的引用。
    reference back(); 返回一个指向vector末元素的引用。
// vector::front/back
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	myvector.push_back(78);
	myvector.push_back(16);
	// now front equals 78, and back 16
	myvector.front() -= myvector.back();
	std::cout << "myvector.front() is now " << myvector.front() << '\n';
	return 0;
}
myvector.front() is now 62
  • data
    value_type* data() noexcept;
    返回一个指向vector首元素的指针。
// vector::data
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector(5);

	int* p = myvector.data();
	*p = 10;
	++p;
	*p = 20;
	p[2] = 100;// 注意,前面有++p,此时p[2]就等于数组的p[3]了

	std::cout << "myvector contains:";
	for (unsigned i = 0; i < myvector.size(); ++i)
		std::cout << ' ' << myvector[i];
	std::cout << '\n';
	return 0;
}
myvector contains: 10 20 0 100 0
修改器(Modifiers)
  • assign
// vector assign
#include <iostream>
#include <vector>
int main() {
	std::vector<int> first;
	std::vector<int> second;
	std::vector<int> third;

	first.assign(7, 100);// 7 ints with a value of 100

	std::vector<int>::iterator it;
	second.assign(first.begin() + 1, first.end() - 1);// the 5 central values of first

	int myints[] = { 1776, 7, 4 };
	third.assign(myints, myints + 3);   // assigning from array.

	std::cout << "Size of first: " << int(first.size()) << '\n';
	std::cout << "Size of second: " << int(second.size()) << '\n';
	std::cout << "Size of third: " << int(third.size()) << '\n';
	return 0;
}
Size of first: 7
Size of second: 5
Size of third: 3
  • push_back、pop_back
// vector::push_back、pop_back
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	int sum(0);
	myvector.push_back(100);
	myvector.push_back(200);
	myvector.push_back(300);
	while (!myvector.empty()) {
		sum += myvector.back();
		myvector.pop_back();// 致使最后myvector是empty的
	}
	std::cout << "The elements of myvector add up to " << sum << '\n';
	return 0;
}
The elements of myvector add up to 600
  • insert
single element (1)	iterator insert (iterator position, const value_type& val);
fill (2)	        void insert (iterator position, size_type n, const value_type& val);
range (3)	        template <class InputIterator>
                    void insert (iterator position, InputIterator first, InputIterator last);

在指定位置的前面插入新元素。

// inserting into a vector
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector(3, 100);// 100,100,100
	std::vector<int>::iterator it;

	it = myvector.begin();// *it==100
	it = myvector.insert(it, 200);// 在"it"所在位置上插入200,此时"it"位置为新插入元素的位置,*it==200

	myvector.insert(it, 2, 300);// 在"it"所在位置上插入2个300,即[300,300],200,100,100,100

	// "it" no longer valid, get a new one:
	it = myvector.begin();// 把"it"位置定位到首元素

	std::vector<int> anothervector(2, 400);
	/*=> 300,300,[400,400],200,100,100,100*/
	myvector.insert(it + 2, anothervector.begin(), anothervector.end());
	int myarray[] = { 501, 502, 503 };
	/*=> [501,502,503],300,300,400,400,200,100,100,100*/
	myvector.insert(myvector.begin(), myarray, myarray + 3);

	std::cout << "myvector contains:";
	for (it = myvector.begin(); it < myvector.end(); it++)
		std::cout << ' ' << *it;
	std::cout << '\n';
	return 0;
}
myvector contains: 501 502 503 300 300 400 400 200 100 100 100
  • erase
// erasing from vector
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	// set some values (from 1 to 10)
	for (int i = 1; i <= 10; i++) 
		myvector.push_back(i);

	// erase the 6th element
	myvector.erase(myvector.begin() + 5);
	// erase the first 3 elements:
	myvector.erase(myvector.begin(), myvector.begin() + 3);

	std::cout << "myvector contains:";
	for (unsigned i = 0; i < myvector.size(); ++i)
		std::cout << ' ' << myvector[i];
	std::cout << '\n';
	return 0;
}
myvector contains: 4 5 7 8 9 10
  • clear
// clearing vectors
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	myvector.push_back(100);
	myvector.push_back(200);
	myvector.push_back(300);

	std::cout << "myvector contains:";
	for (unsigned i = 0; i < myvector.size(); i++)
		std::cout << ' ' << myvector[i];
	std::cout << '\n';

	myvector.clear();
	myvector.push_back(1101);
	myvector.push_back(2202);

	std::cout << "myvector contains:";
	for (unsigned i = 0; i < myvector.size(); i++)
		std::cout << ' ' << myvector[i];
	std::cout << '\n';
	return 0;
}
myvector contains: 100 200 300
myvector contains: 1101 2202
  • swap
    void swap(vector& x);
// swap vectors
#include <iostream>
#include <vector>
int main() {
	std::vector<int> foo(3, 100);// three ints with a value of 100
	std::vector<int> bar(5, 200);// five ints with a value of 200

	foo.swap(bar);

	std::cout << "foo contains:";
	for (unsigned i = 0; i < foo.size(); i++)
		std::cout << ' ' << foo[i];
	std::cout << '\n';

	std::cout << "bar contains:";
	for (unsigned i = 0; i < bar.size(); i++)
		std::cout << ' ' << bar[i];
	std::cout << '\n';
	return 0;
}
foo contains: 200 200 200 200 200 
bar contains: 100 100 100
  • emplace /ɪmˈpleɪs/ [em]+[place] = 安放
    template <class... Args>
    iterator emplace(const_iterator position, Args&&... args);
    构造和插入元素。
// vector::emplace
#include <iostream>
#include <vector>
int main() {
    std::vector<int> myvector = { 10, 20, 30 };
    auto it = myvector.emplace(myvector.begin() + 1, 100);//10,[100],20,30
    myvector.emplace(it, 200);//10,[200],100,20,30
    myvector.emplace(myvector.end(), 300);//10,200,100,20,30,[300]
    std::cout << "myvector contains:";
    for (auto& x : myvector)
        std::cout << ' ' << x;
    std::cout << '\n';
    return 0;
}

注意,以上*myvector.begin() == 10,而*myvector.end() == 0。即,vector.begin()返回的是首元素地址,而vector.end()返回的是末元素的下一个元素。

myvector contains: 10 200 100 20 30 300
  • emplace_back
    template <class... Args> void emplace_back(Args&&... args);
    构造和在末尾插入元素。
// vector::emplace_back
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector = {10, 20, 30};
	myvector.emplace_back(100);
	myvector.emplace_back(200);
	std::cout << "myvector contains:";
	for (auto& x : myvector)
		std::cout << ' ' << x;
	return 0;
}
myvector contains: 10 20 30 100 200
分配器(Allocator)

allocator_type get_allocator() const noexcept;
返回vector关联的allocator对象的一个副本。

// vector::get_allocator
#include <iostream>
#include <vector>
int main() {
	std::vector<int> myvector;
	int* p;
	unsigned int i;

	// allocate an array with space for 5 elements using vector's allocator:
	p = myvector.get_allocator().allocate(5);

	// construct values in-place on the array:
	for (i = 0; i < 5; i++) 
		myvector.get_allocator().construct(&p[i], i);

	std::cout << "The allocated array contains:";
	for (i = 0; i < 5; i++) 
		std::cout << ' ' << p[i];
	std::cout << '\n';

	// destroy and deallocate:
	for (i = 0; i < 5; i++) 
		myvector.get_allocator().destroy(&p[i]);// 销毁
	myvector.get_allocator().deallocate(p, 5);// 解除分配
	return 0;
}
The allocated array contains: 0 1 2 3 4
非成员函数重载(Non-member function overloads)
  • swap
// swap (vector overload)
#include <iostream>
#include <vector>
main() {
	unsigned int i;
	std::vector<int> foo(3, 100);
	std::vector<int> bar(5, 200);
	swap(foo, bar);// 非成员函数重载swap函数
	std::cout << "foo contains:";
	for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';
	std::cout << "bar contains:";
	for (std::vector<int>::iterator it = bar.begin(); it != bar.end(); ++it)
		std::cout << ' ' << *it;
	return 0;
}
foo contains: 200 200 200 200 200 
bar contains: 100 100 100
  • relational operators(关系运算符)
(1)	template <class T, class Alloc>
    bool operator== (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
(2)	template <class T, class Alloc>
    bool operator!= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
(3)	template <class T, class Alloc>
    bool operator<  (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
(4)	template <class T, class Alloc>
    bool operator<= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
(5)	template <class T, class Alloc>
    bool operator>  (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
(6)	template <class T, class Alloc>
    bool operator>= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// vector comparisons
#include <iostream>
#include <vector>
int main() {
	std::vector<int> foo(3, 100);
	std::vector<int> bar(2, 200);

	if (foo == bar) std::cout << "foo and bar are equal\n";
	if (foo != bar) std::cout << "foo and bar are not equal\n";
	if (foo < bar) std::cout << "foo is less than bar\n";
	if (foo > bar) std::cout << "foo is greater than bar\n";
	if (foo <= bar) std::cout << "foo is less than or equal to bar\n";
	if (foo >= bar) std::cout << "foo is greater than or equal to bar\n";
	return 0;
}
foo and bar are not equal
foo is less than bar
foo is less than or equal to bar
模板具体化(Template specializations)

std::vector<bool>
template <class T, class Alloc = allocator<T>> class vector;// 常规模板
template<class Alloc> class vector<bool, Alloc>;// bool类型具体化
成员类(Member classes)
std::vector<bool>::reference
class reference;
当直接访问它的元素时,这个内嵌类返回的类型成员是non-const vector<bool>。它用一个接口访问单个比特来模拟一个bool引用。
它的原型(prototype)是:

class vector<bool>::reference {
	friend class vector;
	reference() noexcept;// no public constructor
public:
	~reference();
	operator bool() const noexcept;// convert to bool
	reference& operator= (const bool x) noexcept;// assign from bool
	reference& operator= (const reference& x) noexcept;// assign from bit
	void flip();// flip bit value.
};

成员函数(Member functions)

  • flip
    翻转(flip)容器中的所有值,所有true变为false,所有false变为true。
// vector<bool>::flip
#include <iostream>
#include <vector>
int main() {
	std::vector<bool> mask;
	mask.push_back(true);
	mask.push_back(false);
	mask.push_back(false);
	mask.push_back(true);
	mask.flip();// 翻转
	std::cout << std::boolalpha;
	std::cout << "mask contains:";
	for (unsigned i = 0; i < mask.size(); i++)
		std::cout << ' ' << mask.at(i);
	return 0;
}
mask contains: false true true false
  • swap
    void swap(vector& x);// 交换容器
    static void swap(reference ref1, reference ref2) noexcept;// 交换元素
// vector<bool>::swap
#include <iostream>
#include <vector>
int main() {
	std::vector<bool> foo;
	std::vector<bool> bar;
	foo.push_back(false);
	foo.push_back(true);
	foo.push_back(false);

	bar.push_back(true);
	bar.push_back(false);

	foo.swap(foo[0], foo[1]);
	bar.swap(bar.front(), bar.back());
	foo.swap(bar);

	std::cout << std::boolalpha;
	std::cout << "foo contains:";
	for (unsigned i = 0; i < foo.size(); i++)
		std::cout << ' ' << foo[i];
	std::cout << "\nbar contains:";
	for (unsigned i = 0; i < bar.size(); i++)
		std::cout << ' ' << bar[i];
	return 0;
}
foo contains: false true
bar contains: true false false

非成员类具体化
std::hash<vector<bool>>
template <class T> struct hash;// 非具体化
template <class Alloc> struct hash<vector<bool, Alloc>>;// vector<bool>
一元函数对象类,它定义了vector<bool>的hash具体化。
函数调用返回一个基于整个vector的hash值:一个hash值仅取决于其参数,对于同一参数总是返回相同的值(对于一个给定的执行程序)。

  • 成员函数(Member functions)
    operator() 为它的参数返回一个size_t类型的hash值。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值