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

Posted itzyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cpp►STL容器->序列容器->vector相关的知识,希望对你有一定的参考价值。

描述

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
#cpp►STL容器->序列容器->deque

STL里容器vector部分用法

cpp的stl有linklist吗

❤️ STL 序列式容器 vector 超硬核源码剖析 ❤️

STL学习笔记--4序列式容器之vector

C++容器Vector问题