文章目录
- 1.vector的介绍及使用(顺序表)
-
- [1.1 vector的介绍[vector参考文献](https://legacy.cplusplus.com/reference/)](#1.1 vector的介绍vector参考文献)
- [1.2 vector的使用](#1.2 vector的使用)
-
- [Member functions](#Member functions)
-
- [(1) (constructor) std::vector::vector[构造](https://legacy.cplusplus.com/reference/vector/vector/vector/)](#(1) (constructor) std::vector::vector构造)
- Iterators(迭代器):
-
- (1)正向迭代器std::vector::begin
- (2)正向迭代器std::vector::end
- (3)反向向迭代器std::vector::rbegin
- [(4)反向向迭代器 std::vector::rend](#(4)反向向迭代器 std::vector::rend)
- Capacity:
- [Element access:](#Element access:)
- Modifiers:
-
- (2)assign
- (3)std::vector::pop_back
- (4)std::vector::insert(不能像string那样用下标插入了)头插
- [(5)erase 删](#(5)erase 删)
- (6)emplace
- Allocator:
- [Non-member function overloads](#Non-member function overloads)
- [Template specializations](#Template specializations)
- 拓展
- 2.vector深度剖析及模拟实现
-
- [2.1 std::vector的核心框架接口的模拟实现st::vector](#2.1 std::vector的核心框架接口的模拟实现st::vector)
- [2.2 使用memcpy拷贝问题](#2.2 使用memcpy拷贝问题)
- 补充
- 总结
1.vector的介绍及使用(顺序表)

1.1 vector的介绍vector参考文献

三种遍历方式
(1)遍历第一种下标
(2)第二种迭代器
(3)范围for 支持迭代器就支持范围for
具体代码实现如下图:
cpp
vector<int> v1;
vector<int> v2(10, 1);
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
//遍历第一种下标
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
//第二种迭代器
vector<int>::iterator it1 = v1.begin();//像指针一样的东西,在指定类域里操作
while (it1!=v1.end())
{
cout << *it1 << " ";
++it1;
}
cout << endl;
//范围for 支持迭代器就支持范围for
for (auto e : v1)
{
cout << e<< " ";
}
cout << endl;

1.2 vector的使用
Member functions
(1) (constructor) std::vector::vector构造

cpp
vector<int> v1;
vector<int> v2(10, 1);
cpp
vector<int> v1 = { 1,2,3,4,5,6 };
上面的代码调用了下面这个:
cpp
void test_vector1()
{
vector<int> v1 = { 1,2,3,4,5,6 };
vector<int> v2 ({ 1,2,3,4,5,6 });
auto il1 = { 1,2,3,4,5,6 };
initializer_list<int> il2 = { 1,2,3,4,5,6 };
//int a[] = { 1,2,3,4,5,6 };
}
initializer_list底层有两个指针,如下图:
Iterators(迭代器):
(1)正向迭代器std::vector::begin

(2)正向迭代器std::vector::end

(3)反向向迭代器std::vector::rbegin

(4)反向向迭代器 std::vector::rend

Capacity:
一般最好不要使用shrink_to_fit接口,因为平常都是删除数据,不会改变空间大小(如下图)
Element access:

Modifiers:
####(1) push_back
具体使用在三种遍历方式那;
(2)assign

cpp
v1.assign({ 10,20,30 });
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;

(3)std::vector::pop_back

(4)std::vector::insert(不能像string那样用下标插入了)头插

cpp
v1.insert(v1.begin(),10);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
v1.insert(v1.begin()+2, 1000);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;

(5)erase 删

cpp
v1.erase(v1.begin() + 2);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}

(6)emplace

Allocator:

Non-member function overloads

Template specializations

拓展
1.sting,vector区别
1.类型不同
cpp
string s1;
vector<char> v3;
2、string定义的s1是有/0的,vector定义v3没有/0;
3.string能串,vector不行,string又operator[]+=...;vector 没有#
用string实例化一个vector,使用范围for
用string实例化一个vector底层原理 (如下图)
vstr.push_back("李四");//隐式类型转换 在调用string(const char* str);
for (const auto& e : vstr)//v1不是int类型加const auto& ;不然消耗太大这两个很重要
cpp
vector<string> vstr;//用string实例化一个vector
string s1 = "张三";
vstr.push_back(s1);
vstr.push_back("李四");//隐式类型转换 在调用string(const char* str);
for (const auto& e : vstr)//v1不是int类型加const auto& ;不然消耗太大
{
cout << e << " ";
}
cout << endl;

vstr[][]和vstr.operator<>.operator<>++两者等价
过程如下:
vstr[0][1]++;//变同音词
vstr[0][1]++;
vstr.operator.operator++;//与上方代码等价
cpp
//vstr[0][0]++;
vstr[0][1]++;//变同音词
vstr[0][1]++;
vstr.operator[](0).operator[](1)++;//与上方代码等价
for (const auto& e : vstr)//v1不是int类型加const auto& ;不然消耗太大
{
cout << e << " ";
}
cout << endl;

扩容问题
capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2
倍增长的。
cpp
// 测试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';
}
}
}
// 如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够
// 就可以避免边插入边扩容导致效率低下的问题了
void TestVectorExpandOP()
{
vector<int> v;
size_t sz = v.capacity();
v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
cout << "making bar 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';
}
}
}
int main()
{
//test_vector1();
TestVectorExpand();
TestVectorExpandOP();
return 0;
}

练习
1

cpp
class Solution {
public:
int singleNumber(vector<int>& nums) {
int value = 0;
for(auto e:nums)
{
value ^= e;
}
return value;
}
};
2.杨辉三角
在c语言上的逻辑
how 开辟空间的:
cpp
int row =0;
int *colArr = NULL;
ptr = generate(10,&row,&colArr);//int** colArr为指针,再取地址;
int**ptr =(int**)malloc(sizeof(int*)*N);
for(int i = 0;i<N ;i++)
{
ptr[i] =(int*)malloc(sizeof(int)*(i+1));
}
c++
cpp
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vv(numRows,vector<int>());
for(size_t i =0;i<numRows;++i)
{
vv[i].resize(i+1,1);//全是1;
}
for(size_t i = 0;i < vv.size();++i)
{
for(size_t j = 1;j < vv[i].size()-1;++j)//第一个,最后一个不需要动
{
vv[i][j]=vv[i-1][j]+vv[i-1][j-1];//上一行的前一个和前一行的后一个相加
}
}
return vv;
}
};
vector 和vector<vector>区别和动态二维数组理解
本质实例化出两个类型
vector
vector<vector>
cpp
//vector
template<class T>
class vector
{
public:
T& operator[](size_t i)
{
assert(i < _size);
return _a[i];
}
private:
T* _a;
size_t _size;
size_t _capacity;
};
详细分解如下图:
2.vector深度剖析及模拟实现
2.1 std::vector的核心框架接口的模拟实现st::vector
vector.h
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace st
{
template <class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{}
vector(initializer_list<T> il)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(il.size());
for (auto& e : il)//加引用,万一类型不是整形
{
push_back(e);
}
}
~vector()
{
delete[]_start;
_start = _finish = _endofstorage = nullptr;
}
T& operator[](size_t i)
{
assert(i < size());
return _start[i];
}
const T& operator[](size_t i) const
{
assert(i < size());
return _start[i];
}
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _endofstorage - _start;
}
void resize(size_t n, T val = T())//匿名对象缺省值
{
if (n <= size())
{
_finish = _start + n;
}
else
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
}
void reserve(size_t n)
{
if (n > capacity())
{
size_t Oldsize = size();
T* tmp = new T[n];
if (_start)
{
memcpy(tmp, _start, sizeof(T) * Oldsize);//拷贝
delete[] _start;
}
_start = tmp;
_finish = _start + Oldsize;
_endofstorage = _start + n;
}
}
void push_back(const T& x)
{
//复用
//insert(_finish, x);//在finish这个位置插入x
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
}
*_finish = x;
++_finish;
}
bool empty()
{
return _start == _finish;
}
void pop_back()//尾删
{
assert(!empty());//不能为空
--_finish;
}
//迭代器失效,本质因为一些原因,迭代器不可用
//void insert(iterator pos, const T& x)
//{
// assert(pos >= _start && pos <= _finish);
// //空间不够,扩二倍
// if (_finish == _endofstorage)
// {
// size_t len = pos - _start;
// reserve(capacity() == 0 ? 4 : capacity() * 2);
// pos = _start + len;
// }
// iterator i = _finish - 1;
// while (i >= pos)
// {
// *(i + 1) = *i;
// --i;
// }
// *pos = x;
// ++_finish;
//}
//修改
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish);
//空间不够,扩二倍
if (_finish == _endofstorage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator i = _finish - 1;
while (i >= pos)
{
*(i + 1) = *i;
--i;
}
*pos = x;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
iterator i = pos + 1;
while (i < _finish)
{
*(i - 1) = *i;//覆盖往后挪
i++;
}
_finish --;
return pos;
}
private:
iterator _start;//头 _a
iterator _finish;//尾 _finsh-_start ==_size
iterator _endofstorage;//末 _endofstorage-_start ==_capacity;
};
void test_vector1()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int>::iterator it1 = v1.begin();
while (it1 != v1.end())
{
cout << *it1 << " ";
++it1;
}
cout << endl;
v1.pop_back();
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector2()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
v1.insert(v1.begin() + 2, 30);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int> v2 = { 1,2,3,4,5,6,7 };
for (auto e : v2)
{
cout << e << " ";
}
cout << endl;
}
void test_vector3()
{
std::vector<int> v1;
//vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
int x;
cin >> x;
auto it = find(v1.begin(), v1.end(), x);
//if(it != v1.end())
//{
// //it是否失效? 失效了,不能访问
// it = v1.insert(it, 10 * x);
// cout <<*it << endl;//失效了
//}
if (it != v1.end())
{
it = v1.insert(it, 10 * x);
cout << *it << endl;//失效了
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector4()
{
std::vector<int> v1;
/*vector<int> v1;*/
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
int x;
cin >> x;
auto it = find(v1.begin(), v1.end(), x);
if (it != v1.end())
{
//it是否失效? 失效了,不能访问
v1.erase(it);
cout << *it << endl;
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector5()
{
std::vector<int> v1;
/*vector<int> v1;*/
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//要求删除所有的偶数
auto it = v1.begin();
while (it != v1.end())
{
if (*it % 2 == 0)
{
//erase 返回删除位置下一个位置。
it = v1.erase(it);
}
else ++it;
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector6()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
v1.resize(10);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
v1.resize(15,1);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
}
test.cpp
cpp
#include<iostream>
#include<vector>
using namespace std;
void test_vector1()
{
vector<int> v1{ 1,2,3,4,5,6 };
vector<int> v2({ 1,2,3,4,5,6 });
//auto il1 = { 1,2,3,4,5,6 };
//initializer_list<int> il2 = {1,2,3,4,5,6};
//int a[] = {1,2,3,4,5,6,7};
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//v1[10]
v1.assign({ 10,20,30 });
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
v1.insert(v1.begin() ,9);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
v1.insert(v1.begin() + 2, 200);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void TestVectorExpand()
{
size_t sz;
vector<int> v;
cout << typeid(vector<int>::iterator).name() << endl;//查看类型
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';
}
}
}
void test_vector2()
{
TestVectorExpand();
}
#include"vector.h"
int main()
{
//test_vector1();
//st::test_vector2();
/*st::test_vector3();*/
/*st::test_vector4();*/
/*st::test_vector5();
int i = int();
int i = int(1);
int k(2);*/
st::test_vector6();
return 0;
}
2.2 使用memcpy拷贝问题
2.2.1.浅拷贝

2.2.2深拷贝
vector.h
cpp
//深拷贝 拷贝构造 v2(v1)
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto& e : v)
{
push_back(e);
}
}
void swap(vector<T>& tmp)
{
std::swap(_start, tmp._start);
std::swap(_finish, tmp._finish);
std::swap(_endofstorage, tmp._endofstorage);
}
// v1 = v3 现代写法
vector <T>& operator = (vector<T> v)
{
swap(v); //v3是v想要的,v是v1想要的直接交换
return *this;
}
~vector()
......................................................................................
void test_vector7()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//值拷贝,浅拷贝
vector<int> v2(v1);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int>v3 = { 10,20,30,40 };
v1 = v3;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}

深层次深浅拷贝问题
下方是浅拷贝的代码段和过程,问题是出在memcpy,string中,_str指针指向的内容会析构两次,乱码。

下面是深拷贝过程及修改
cpp
void reserve(size_t n)
{
if (n > capacity())
{
size_t Oldsize = size();
T* tmp = new T[n];
if (_start)
{
//memcpy(tmp, _start, sizeof(T) * Oldsize);//拷贝
for (size_t i = 0; i < Oldsize; i++)
{
tmp[i] = _start[i];//赋值 是深拷贝
}
delete[] _start;
}
_start = tmp;
_finish = _start + Oldsize;
_endofstorage = _start + n;
}
}

补充
迭代器失效问题(insert和erase)
由于扩容引起野指针问题
cpp
void test_vector3()
{
std::vector<int> v1;
//vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
int x;
cin >> x;
auto it = find(v1.begin(), v1.end(), x);
//if(it != v1.end())
//{
// //it是否失效? 失效了,不能访问
// it = v1.insert(it, 10 * x);
// cout <<*it << endl;//失效了
//}
if (it != v1.end())
{
it = v1.insert(it, 10 * x);
cout << *it << endl;//失效了
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
}
迭代器失效问题(erase)
任何场景下,迭代器都会失效,要更新后再去访问。eg:修改后的代码段//erase 返回删除位置下一个位置。
删除数据,导致数据挪动,it已经不是指向之前位置了。it也失效了,因为it已经不是指向之前的位置,可能会导致逻辑问题。
erase模拟实现的过程如下:
vs报错的原因:强制的检查,失效迭代器不让你访问。
cpp
void test_vector4()
{
std::vector<int> v1;
/*vector<int> v1;*/
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
int x;
cin >> x;
auto it = find(v1.begin(), v1.end(), x);
if (it != v1.end())
{
//it是否失效? 失效了,不能访问
v1.erase(it);
cout << *it << endl;
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}

erase迭代器失效的复杂场景(要求删除所有的偶数)
cpp
void test_vector5()
{
std::vector<int> v1;
/*vector<int> v1;*/
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//要求删除所有的偶数
auto it = v1.begin();
while (it != v1.end())
{
if (*it % 2 == 0)
{
v1.erase(it);
}
++it;
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
修改后
cpp
//要求删除所有的偶数
auto it = v1.begin();
while (it != v1.end())
{
if (*it % 2 == 0)
{
//erase 返回删除位置下一个位置。
it = v1.erase(it);
}
else ++it;
}

极端情况,erase下缩容

总结
以上就是vector的全部内容了,写了好多天,一次没看懂,可多次阅读文章。喜欢博主写的内容,可以一键三连支持博主。