vector的介绍
vector的使用文档
vector
是一个可改变数组大小的序列容器vector
和数组一样采取连续的空间存放数据,可以使用方括号访问vector的元素,和数组一样高效。但是vector的大小可以动态增长,而数组不行- 实际上
vector
内部使用一个动态分配的数组存放数据。当插入新元素时,数组会按需重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将所有元素移动到这个数组中。这是一个比较耗时间的策略,因此每当插入一个新元素时,vector并不会每次重新分配大小。 - vector分配策略:vector会分配一些额外的空间用来适应插入元素时的增长,因此实际存储空间比当前元素所占用存储空间要大。不同的库采用不同策略平衡内存使用和重新分配,但无论如何,重新分配只能以对数增长的大小间隔进行,以便在向量末尾插入各个元素可以提供摊销常数时间复杂度
- 与数组相比,vector会消耗更多的内存换取管理存储和更高效的动态增长的能力
- 相比于其他动态增长的容器,vector获取元素和尾部插入删除元素更加高效;对于中间某一个元素插入删除时的效率没有其他容器高效,并且迭代器和引用的一致性不如列表和单向列表。
vector的使用
构造函数
- 空初始化:调用默认构造函数,没有元素
- 填充构造函数:使用
n
个val
初始化vector
,每一个元素的值都是val
- 范围构造函数:使用
[First, Last)
中的元素一次初始化vector
的每一个元素 - 拷贝构造函数:使用已存在的vector初始化新的
vector
void test1()
{
string str("hello world");
vector<int> v1; //vector是一个类模板,显示模板实例化int
vector<int> v2(3, 1); //填充构造,3个1初始化v2;
vector<char> v3(str.begin(), str.end());
//范围构造
vector<int> v4(v2); //拷贝构造
for (auto e : v1)
{
cout << e; //输出为空
}
cout << endl;
for (auto e : v2)
{
cout << e << " "; //1 1 1
}
cout << endl;
for (auto e : v3)
{
cout << e; //hello world
}
cout << endl;
for (auto e : v4)
{
cout << e << " "; //1 1 1
}
cout << endl;
}
赋值重载
operator=
- 功能:将其他
vector
的内容替换当前vector
的值 - 参数:相同类型的
vector
- 返回值:*this
demo:
// 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';//Size of foo: 0
std::cout << "Size of bar: " << int(bar.size()) << '\n';//Size of bar: 3
return 0;
}
迭代器
与string
一样,vector
是数据连续存储
的容器,因此迭代器是指针。
begin/end
begin
- 功能:返回容器第一个元素的指针
- 参数:迭代器函数的参数为空
- 返回值:如果容器是只读的,返回一个只读的迭代器;如果容器可读可写,返回一个可读可写的迭代器。
end
- 功能:返回指向
vector
中最后一个元素的下一个位置
的迭代器。 - 参数:迭代器函数的参数为空
- 如果容器是只读的,返回一个只读的迭代器;如果容器可读可写,返回一个可读可写的迭代器。
demo:
// vector::begin/end
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector;
for (int i=1; i<=5; i++) myvector.push_back(i);
std::cout << "myvector contains:";
for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
std::cout << ' ' << *it; //1 2 3 4 5
std::cout << '\n';
return 0;
}
rbegin/rend
rbegin
- 功能:返回指向
vector
中最后一个元素
的反向迭代器
- 参数:反向迭代器函数的参数为空
- 返回值:如果容器是只读的,返回一个只读的反向迭代器;如果容器可读可写,返回一个可读可写的反向迭代器。
rend
- 功能:返回指向
vector
中第一个元素
的反向迭代器
。 - 参数:反向迭代器函数的参数为空
- 返回值:如果容器是只读的,返回一个只读的反向迭代器;如果容器可读可写,返回一个可读可写的反向迭代器。
demo:
// vector::rbegin/rend
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (5); // 5 default-constructed ints
std::vector<int>::reverse_iterator rit = myvector.rbegin();
int i=0;
for (rit = myvector.rbegin(); 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; //5 4 3 2 1
std::cout << '\n';
return 0;
}
容量相关函数
size
size
- 功能:返回
vector
的有效数据
个数 - 参数:空
- 返回值:类型为
size_type
,等同于size_t
demo:
// vector::size
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myints;
std::cout << "0. size: " << myints.size() << '\n';
for (int i=0; i<10; i++) myints.push_back(i);
std::cout << "1. size: " << myints.size() << '\n';
myints.insert (myints.end(),10,100);
std::cout << "2. size: " << myints.size() << '\n';
myints.pop_back();
std::cout << "3. size: " << myints.size() << '\n';
return 0;
}
output:
0. size: 0
1. size: 10
2. size: 20
3. size: 19
resize
resize
- 功能:改变
vector
的有效元素个数- 如果n<size,有效元素为前
n
个,删除超出的元素(是否会异地缩容取决编译器) - 如果n>capacity,先扩容使
capacity
==n
,再用val
填充剩下的空间 - 如果size<n<capacity,直接用
val
填充capacity-size
个空间
- 如果n<size,有效元素为前
- 参数:
- n:更新后
vector
有效元素个数 - val:填充值
- n:更新后
- 返回值:无
demo:
// 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);
myvector.resize(8,100);
myvector.resize(12);
std::cout << "myvector contains:";
for (int i=0;i<myvector.size();i++)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
output:
myvector contains: 1 2 3 4 5 100 100 100 0 0 0 0
capacity
capacity
- 功能:返回
vector
的容量(最大存储有效元素的个数) - 参数:空
- 返回值:
size_t
类型
demo:
// 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: " << (int) myvector.size() << '\n';
std::cout << "capacity: " << (int) myvector.capacity() << '\n';
std::cout << "max_size: " << (int) myvector.max_size() << '\n';
return 0;
}
output:
size: 100
capacity: 128
max_size: 1073741823
empty
empty
- 功能:判断
vector
是否为空(有效数据个数为0) - 参数:无
- 返回值:
size
==0返回ture
,否则返回false
demo:
// 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;
}
output:
total = 55;
reserve
reserve
- 功能:改变
vector
的capacity
,使得capacity
最少容纳n个数据- 当
n
>capacity
时,扩容至capacity==n
,将原空间数据挪动到扩容后的新空间。 - 当
n
<capacity
时,不做处理。 reserve
不会影响size
- 当
- 参数:
vector
最小的容量,实际capacity
可能会大于n
,类型为size_t
- 返回值:无
demo:
// 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); // 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;
}
output:
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
可以看见,如果提前reserve一段空间,可以减少扩容和数据拷贝的次数从而提高效率。
注意:
不同的编译器对vector扩容机制不同,在VS下扩容后是扩容前空间的1.5倍,g++下是2倍
shrink_to_fit
shrink_to_fit
- 功能:减少容器的
capacity
以适应其尺寸,函数可能会realloc
,但是对size
无影响。 - 参数:无
- 返回值:无
- 注意:该函数没有约束力,容器可以进行自由的优化,使其
capacity
>size
。
demo:
// 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;
}
output:
1. capacity of myvector: 100
2. capacity of myvector: 100
3. capacity of myvector: 10
获取元素
operator[]
operator[]
- 功能:返回vector中第n个元素的引用。与
vector::at
具有相同功能,不同的是vector::at
进行了边界检查,并通过抛出out_of_range
异常来指示请求的位置是否超出范围。 - 参数:n是容器中第n个元素,类型为
size_t
- 返回值:第n个元素的引用,如果是
const vector
,返回常引用
,否则返回引用
demo:
// vector::operator[]
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (10); // 10 zero-initialized elements
std::vector<int>::size_type sz = myvector.size();
// assign some values:
for (unsigned i=0; i<sz; i++) myvector[i]=i;
// reverse vector using operator[]:
for (unsigned i=0; i<sz/2; i++)
{
int temp;
temp = myvector[sz-1-i];
myvector[sz-1-i]=myvector[i];
myvector[i]=temp;
}
std::cout << "myvector contains:";
for (unsigned i=0; i<sz; i++)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
output:
myvector contains: 9 8 7 6 5 4 3 2 1 0
data
data
- 功能:返回一个指向
vector
用于内部存储数据的数组的指针。因为vector
数据是连续存储的,所以可以通过data偏移量
访问vector
中的数据,例如v.data()[1]==v[1] - 参数:空
- 返回值:指向第一个数据的指针。如果
vector
只读,指针指向的类型是const_value_type
,否则指针指向的类型是value_type
demo:
// 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;
std::cout << "myvector contains:";
for (unsigned i=0; i<myvector.size(); ++i)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
output:
myvector contains: 10 20 0 100 0
修改
assign
assign
- 功能:用数据覆盖
vector
原本的内容,并合适地修改size
。当且仅当新的容器大小大于当前vector
时,数组会realloc
- 参数:
- 范围分配:
first
和last
是其他容器的迭代器,first
是序列的初始位置,last
是序列的结束位置,将[first,last)
中的值分配给vector
,这些值包括first
不包括last
。 - 填充分配:
n
是vector
的size
大小,类型为size_t
,用n
个val
填充vector
- 范围分配:
- 返回值:空
demo:
// 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;
it=first.begin()+1;
second.assign (it,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;
}
output:
Size of first: 7
Size of second: 5
Size of third: 3
push_back
push_back
- 功能:将
val
值插入到vector
尾部。尾插后size
会增加1个大小,当且仅当增加后的size>capacity时,分配的存储空间会realloc
。 - 参数:要复制到尾部的值,是一个常引用
- 返回值:空
- 注意:
- 如果发生了
realloc
,那么realloc
的时间与vector
的size
成线性函数。 - 如果发生了
realloc
,那么所有的迭代器,指针,引用都会失效,否则只有end_iterator
是失效的,其他的迭代器,指针引用都和调用前指向相同。 - 如果发生了
realloc
,所有的元素都会被复制到新分配的空间中。
- 如果发生了
demo:
// vector::push_back
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector;
int myint;
std::cout << "Please enter some integers (enter 0 to end):\n";
do {
std::cin >> myint;
myvector.push_back (myint);
} while (myint);
std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n";
return 0;
}
pop_back
pop_back
- 功能:删除
vector
中最后一个元素,size
大小减一。 - 参数:空
- 返回值:空
- 注意:
pop_back
后,任何指向被删除元素的迭代器,指针,引用都失效
demo:
// vector::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();
}
std::cout << "The elements of myvector add up to " << sum << '\n';
return 0;
}
output:
The elements of myvector add up to 600
insert
insert
-
功能:通过在指定位置的元素之前插入新元素来扩展
vector
,从而通过插入元素的数量有效地增加容器大小。当新的size>capacity时,分配的空间会realloc
。 -
参数:
- position:插入元素的位置,
iterator
是一个成员类型,定义为指向元素的random_access_iterator
类型。 - val:插入值的常引用
- n:插入元素的个数,类型为
size_t
- first,last:指定添加元素范围的区间。
[first,last)
范围内的元素副本将插入到position
位置(以相同的顺序)。范围包括first
不包括last
。first
和last
都是vector::iterator
类型。
- position:插入元素的位置,
-
返回值:返回一个指向新插入的第一个元素迭代器,返回值类型为
vector::iterator
-
注意:
-
时间复杂度:与插入的元素数量(复制/移动构造)加上位置后的元素数量(移动)成线性关系。若不是在vector末尾插入元素,效率通常不会很高 O ( n ) O(n) O(n)
-
迭代器失效:如果内存分配发生
realloc
,那么所有的迭代器,指针,引用都会失效;否则只有指向position
之后的迭代器,指针,引用会失效,指向position
之前的迭代器,指针,引用不会失效。
-
demo:
// inserting into a vector
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (3,100);
std::vector<int>::iterator it;
it = myvector.begin();
it = myvector.insert ( it , 200 );
myvector.insert (it,2,300);
//After reallocation, "it" no longer valid, get a new one:
it = myvector.begin();
std::vector<int> anothervector (2,400);
myvector.insert (it+2,anothervector.begin(),anothervector.end());
int myarray [] = { 501,502,503 };
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;
}
output:
myvector contains: 501 502 503 300 300 400 400 200 100 100 100
erase
erase
- 功能:从
vector
中删除单个元素或删除一段迭代器区间。size
大小减一。 - 参数:
- position:指向
vector
中需要被删除的元素。vector::iterator
和vector::const_iterator
都是成员类型,也是random_access_iterator
。 - first,last:指定要删除
vector
的区间,包括[first,last)
中的所有元素,即包括first
不包括last
。first
和last
都是vector::iterator
类型,即random_access_iterator
。
- position:指向
- 返回值:返回一个指向最后一个被删除元素的下一个新位置的迭代器。
- 注意:
- 时间复杂度:与删除(破坏)的元素数量加上最后一个元素删除(移动)之后的元素数量成线性关系。处尾删外,删除效率不是很高 O ( n ) O(n) O(n)
- 迭代器失效:指向
position
(或first
)及以后元素的迭代器、指针和引用将失效,而指向position
(或first
)之前元素的所有迭代器、指针和引用将保证继续指向调用前所指向的相同元素。
demo:
/ 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;
}
output:
myvector contains: 4 5 7 8 9 10
swap
swap
- 功能:用另一个
vector
的内容交换当前vector
的内容,两个vector
的类型相同,size
可能不同 - 参数:需要交换内容的
vector
引用x
,x
与当前vector
具有相同类型。 - 返回值:空
- 注意:
- 成员函数
swap
是通过非成员库函数swap
实现的 vector
的bool
特化为此函数提供了额外的重载vector<bool>::swap
- 成员函数
demo:
// 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;
}
output:
foo contains: 200 200 200 200 200
bar contains: 100 100 100
clear
(clear)[https://cplusplus.com/reference/vector/vector/clear/]
- 功能:移除
vector
中的所有元素,让size=0。 - 参数:空
- 返回值:空
- 注意:
- 调用该函数不能保证会发生
realloc
,也不能保证capacity
会改变。强制清空capacity
可以通过使用swap函数vector<T>().swap(x)
。 - 复杂度:和
size
大小线性相关 - 迭代器失效:
vector
中的所有迭代器都失效
- 调用该函数不能保证会发生
demo:
// 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;
}
output:
myvector contains: 100 200 300
myvector contains: 1101 2202
vector的实现
成员变量
T* _start:指向存储空间的起始位置
T* _finish:指向最后一个有效数据的下一个位置
T* _end_of_storage:指向最后一个有效存储空间的下一个位置
迭代器
iterator:T*的重定义。
const_iterator:const T*的重定义。
成员函数
构造/析构函数
注意:
- 在执行拷贝构造函数时,需要考虑
深拷贝
的问题~ - range构造函数中first和last的类型是一样的,所以我们调用vector<int>(10,1)时,我们想用10个1去构造,但是编译器可能会识别为10和1全部都是迭代器,此时解引用就会造成非法访问,解决办法就是在fill构造函数中将第一个参数类型指定为int ,这样编译器在模板参数和显示参数中选择调用带有显示参数的构造函数,也就是我们想要的fill构造函数。
template<typename T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
vector() //default构造函数
{
_start = _finish = _end_of_storage = nullptr;
}
vector(int sz, const T& val = T())
{ //fill构造函数,sz的类型为int让编译器区分构造vector<int>(3,1)类型时调用的是fill构造而不是range构造
//为vector申请sz个空间
_finish = _start = new T[sz];
//fill构造时,_end_of_storage和_finish指向同个位置
_end_of_storage = _start + sz;
//这里也可以*_finish++ = val;
for (size_t i = 0; i < sz; i++)
{
push_back(val);
}
}
vector(const vector<T>& v)
{ //拷贝构造函数
//v的size
int sz = v._finish - v._start;
//v的capacity
int capacity = v._end_of_storage - v._start;
_start = new T[capacity];
//注意:这里依次让v的每个元素赋值给*this,当*this类似于string类型时赋值可以调用string的深拷贝
//不能简单的使用memcpy,memcpy是浅拷贝
for (size_t i = 0; i < sz; i++)
{
_start[i] = v._start[i];
}
//更新_finish和_end_of_storage
_finish = _start + sz;
_end_of_storage = _start + capacity;
}
//range构造函数
template<typename InputerIterator>
vector(InputerIterator first, InputerIterator last)
{
//数据区间为[first,last)
while (first != last)
{ //等效于*_finish++ = *first++;
push_back(*first++);
//first++;
}
}
~vector()
{ //new的空间delete,防止MemoryLeak
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
测试结果:
赋值重载
注意:当vector类型为string等,考虑深拷贝
问题
//赋值重载函数
vector<T>& operator=(const vector<T>& v)
{
int sz = v._finish - v._start;
int capacity = v._end_of_storage - v._start;
//start指向sz个空间
_start = new T[sz];
for (size_t i = 0; i < sz; i++)
{ //使用赋值考虑深拷贝的问题
*_finish++ = v[i];
}
//更新_end_of_storage
_end_of_storage = _start + capacity;
return *this;
}
测试结果:
迭代器
//迭代器
iterator begin()
{
return _start;
}
const_iterator begin() const
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator end() const
{
return _finish;
}
测试结果:
容量相关函数
注意:
- 实现扩容相关函数时,涉及到将原空间数据拷贝到新空间中,所以需要考虑
深拷贝
问题
rsize_t capacity() const
{
return _end_of_storage - _start; //_end_of_storage和_start之间是存储空间
}
rsize_t size() const
{
return _finish - _start; //_finish和_start之间是有效元素
}
void reserve(size_t n) //预先开辟n个空间
{
size_t cap = capacity();
size_t sz = size();
if (n > cap) //当且仅当n大于当前容量扩容
{
T* tmp = new T[n];
//拷贝元数据到新空间,数据拷贝时需要注意深拷贝问题,使用赋值而不用memcpy
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start; //释放原数据空间
//更新_start _finish _end_of_storage
_start = tmp;
_finish = _start + sz;
_end_of_storage = _start + cap;
}
}
void resize(size_t sz, T val = T())
{
size_t _sz = _finish - _start;
size_t _capacity = _end_of_storage - _start;
if (sz < _sz) //情况1.sz小于当前size,直接缩小当前size,capacity不变
{
_finish -= sz;
}
else if (sz <= _capacity) //情况2.size<sz<capacity,直接在剩下的存储空间中插入capacity-
{
while (_sz < sz)
{
push_back(val);
_sz++;
}
}
else //情况3.sz>capacity,先扩容,在插入sz-size个val
{
reserve(sz);
while (_sz < sz)
{
push_back(val);
}
}
}
测试结果:
获取元素/修改
注意:
- 当使用insert和erase时,需要注意迭代器失效。
- insert:若插入后扩容了,如果是异地扩容,则原来的迭代器全部失效,需要更新,若没有扩容,原本指向插入位置之后的迭代器失效,之前的没有影响
- erase:删除位置后面的迭代器全部失效,前面的没有影响
/*访问*/
T& operator[](size_t pos)
{
assert(0 <= pos && pos < _finish - _start);
return *(_start + pos);
}
const T& operator[](size_t pos) const
{
assert(0 <= pos && pos < _finish - _start);
return *(_start + pos);
}
T front()
{
return *_start;
}
const T front() const
{
return *_start;
}
T back()
{
return *_finish;
}
const T back() const
{
return *_finish;
}
/*修改类*/
void push_back(const T& val)
{
size_t sz = _finish - _start;
size_t ca = _end_of_storage - _start;
if (ca == sz)
{
reserve(ca == 0 ? 4 : 2 * ca);
}
*_finish = val;
_finish++;
//insert(end(), val);
}
void pop_back()
{
assert(_finish - _start >= 1);
_finish--;
//erase(end() - 1);
}
iterator insert(iterator pos, const T& val)//返回值用于更新扩容前指向pos处的迭代器
{
int sz = _finish - _start;
int capacity = _end_of_storage - _start;
int gap = pos - _start; //记录扩容前_start和pos的相对位置
if (_finish == _end_of_storage) //扩容
{
//2倍扩容
reserve(capacity == 0 ? 4 : 2*capacity);
//此时_start _finish _end_of_storage已经是扩容后的位置了
pos = _start + gap;//修正pos
}
/*挪动数据*/
iterator end = _finish;
while (end > pos)
{
*end = *(end - 1);
end--;
}
*pos = val;
_finish++;
return pos;
}
template<class Inputiterator>
iterator insert(iterator pos, Inputiterator first, Inputiterator last)
{
int num = last - first; //要插入的个数
int sz = _finish - _start;
int capacity = _end_of_storage - _start;
int gap = pos - _start; //_start和pos的相对位置
//当前容量不够插入需要扩容
if (sz + num > capacity)
{
reserve(sz + num);
_finish = _end_of_storage;
pos = _start + gap;
iterator after = pos + num;
iterator before = pos;
while (after < _end_of_storage)
{
*after++ = *before++;
}
while (first < last)
{
*pos++ = *first++;
}
_finish = _end_of_storage;
}
//当前容量够插入
else
{
iterator after = pos + num;
iterator before = pos;
while (before < _finish)
{
*after++ = *before++;
}
while (first < last)
{
*pos++ = *first++;
}
_finish = after;
}
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start); //删除元素位置介于[first,last)
assert(pos < _finish);
iterator begin = pos; //pos后面的元素往前挪
while (begin < _finish - 1)
{
*begin = *(begin + 1);
begin++;
}
_finish--;
return pos;
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
void clear()
{
_finish = _start; //size=0
}
测试结果: