目录
1.Vector介绍
2.Vector的常见使用
2.1 vector构造函数
(constructor)构造函数声明 | 接口说明 |
vector() | 无参构造 |
vector (size_type n,const value_type&val=value_type()) | 构造并初始化n个val |
vector (const vector& x) | 拷贝构造 |
vector (InputIterator fifirst, InputIterator last) | 迭代器进行初始化构造 |
2.2 vector iterator使用
iterator的使用 | 接口说明 |
begin+end |
获取第一个数据位置的 iterator/const_iterator , 获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin+rend |
获取最后一个数据位置的 reverse_iterator ,获取第一个数据前一个位置的reverse_iterator |
简单使用例子:
void test1()
{
vector<int> V;
V.push_back(1);
V.push_back(2);
V.push_back(3);
V.push_back(4);
vector<int>::iterator it = V.begin();
while (it != V.end())
{
cout << *it << ' ';
++it;
}
cout << endl;
//反向迭代器
vector<int>::reverse_iterator rit = V.rbegin();
while (rit != V.rend())
{
cout << *rit << ' ';
++rit;
}
cout << endl;
}
2.3 vector空间增长问题
容量空间 | 接口说明 |
size | 获取数据个数 |
capacity | 获取容量大小 |
empty | 判断是否为空 |
resize | 改变vector的size |
reserve | 改变vector的capacity |
测试vector的默认扩容机制:
void TestVectorExpand()
{
size_t sz;
vector<int> v;
sz = v.capacity();
cout << "making v grow:\n";
for (int i = 0; i < 100; ++i)
{
v.push_back(i);
if (sz != v.capacity())
{
sz = v.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
}
vs下运行:
gcc下运行:
void test2()
{
vector<int> v;
// set some initial content:
for (int i = 1; i < 10; i++)
v.push_back(i);
v.resize(5);
v.resize(8, 100);
v.resize(12);
cout << v.size() << endl;
cout << "v contains:";
for (size_t i = 0; i < v.size(); i++)
cout << ' ' << v[i];
cout << endl;
}
使用reserve提前设置好容量:
2.4 vector增删改查
vector增删改查 | 接口说明 |
push_back | 尾插 |
pop_back | 尾删 |
find | 查找(算法模块实现,不是vector成员接口) |
insert | 在pos前插入val |
erase | 删除pos位置数据 |
swap | 交换两个vector数据空间 |
operator[ ] | 像数组一样下标访问 |
测试代码:
void test3()
{
vector<int> v{ 1,2,3,4 };//列表方式初始化,C++11新语法
v.push_back(5);
v.push_back(6);
v.pop_back();
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << ' ';
}
cout << endl;
vector<int>::iterator pos = find(v.begin(), v.end(), 3);
if (pos != v.end())
{
v.insert(pos, 0);
}
pos = find(v.begin(), v.end(), 3);
v.erase(pos);
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << ' ';
}
cout << endl;
}
2.5 vector迭代器失效问题
细心的朋友,可能已经发现我上面圈出来的重复find查找了一次,这是因为如果不再find给pos赋值,insert后不接受迭代器返回值继续erase会造成迭代器失效问题。
对于vector可能会导致其迭代器失效的有效的操作有:
- 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。
扩容后原来的pos已经失效,变为野指针。
若不扩容insert后pos指向插入元素。
- 指定位置元素的删除——erase
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是: 如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。
迭代器失效解决办法: 在使用前,对迭代器 重新赋值 即可
修改上面例子代码示例如下:
vector<int>::iterator pos = find(v.begin(), v.end(), 3);
if (pos != v.end())
{
pos=v.insert(pos, 0);
//pos当前指向0
}
//删除3
++pos;
v.erase(pos);
3.Vector深度剖析及模拟实现
3.1 模拟实现(可跳过)
私有成员变量:与上图保持一致
iterator _start;
iterator _finish;
iterator _end_of_storage;
构造函数:
拷贝构造函数:(现代写法)
swap:
赋值运算符重载:(现代写法)
析构函数:
迭代器:
size和capacity:
reserve:(为什么不使用memcpy在后面将解)
resize:
operator[ ]:
insert:
erase:
push_back,pop_back():(复用insert,erase)
3.2 不使用memcpy剖析
memcpy是浅拷贝
假设一个vector<vector<int>>类型,实际内存分配:
memcpy分配:(浅拷贝,释放2次空间,第二次为野指针造成内存泄漏)
采取深拷贝(自己实现):