vector容器的学习

1.vector的介绍和使用

1.1vector的介绍

vector的介绍文档:cplusplus.com/reference/vector/vector/

使用STL的三个境界:能用,明理,能扩展、那么我们接下来就学习vector,我们也将按照这个方法来学习。

1.2vector的使用

在学习vector得我时候我们需要对应着相应的文档来学习:cplusplus.com/reference/vector/vector/

vector在实际中非常的重要,在实际中我们熟悉一些常见的接口就可以了,下面我们列出了一些常见的接口 :

大部分函数接口都插入有超链接

1.2.1vector的定义

|----------------------------------------------------------------------------------------|--------------|
| construct(构造函数声明) | 接口说明 |
| vector()(重点) | 无参数构造 |
| 被vector(size_type n, const vaule_type& val = value_type()) | 构造并初始化n个val |
| vector(const vector& x)(重点) | 拷贝构造 |
| vector(InputIterator first, InputIterator last) | 使用迭代器进行初始化构造 |

以下为相应的测试函数,感兴趣的小伙伴可以 自己去验证一下:

cpp 复制代码
int TestVector1()
{
    // constructors used in the same order as described above:
    vector<int> first;                                // empty vector of ints
    vector<int> second(4, 100);                       // four ints with value 100
    vector<int> third(second.begin(), second.end());  // iterating through second
    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 };
    vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));

    cout << "The contents of fifth are:";
    for (vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    return 0;
}

1.2.2vector iterator的使用

|--------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| iterator的使用 | 接口说明 |
| begin+end(重点) | 获取第一个数据的位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator |
| rbegin()+rend() | 获取第一个数据的位置的reverae_iterator, 获取最后一个位置的下一个位置的reverse_literator |

vector的迭代器使用代码演示:

cpp 复制代码
void PrintVector(const vector<int>& v)
{
	// const对象使用const迭代器进行遍历打印
	vector<int>::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

void TestVector2()
{
	// 使用push_back插入4个数据
	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;

	// 使用迭代器进行修改
	it = v.begin();
	while (it != v.end())
	{
		*it *= 2;
		++it;
	}

	// 使用反向迭代器进行遍历再打印
	// vector<int>::reverse_iterator rit = v.rbegin();
	auto rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	PrintVector(v);
}

1.2.3vector的空间增长问题

|---------------------------------------------------------------------------------|-------------------|
| 容量空间 | 接口说明 |
| size | 获取数据的个数 |
| capacity | 获取容器此时的容量 |
| empty | 判断此时容器是否为空 |
| resize(重点) | 改变vector的size |
| reserve(重点) | 改变vector的capacity |

  • capacity的代码在vs和g++下分别运行会发现,vs下的capacity是按照1.5倍增长的,g++时按照2倍增长的。这个问题就经常被考察,不要固化的认为,vector就是以两倍进行增容的,具体增长多少是根据具体的需求进行定义的。vs时PJ版本的STL,g++时SGI版本的STL.
  • reverse只负责派皮空间,如果确定知道需要多少的空间,reserve·可以缓解vector增容的代价缺陷问题。
  • resize在开辟空间的时候还会进行初始化,影响size;

测试函数:

cpp 复制代码
//  vector的resize 和 reserve

// reisze(size_t n, const T& data = T())
// 将有效元素个数设置为n个,如果时增多时,增多的元素使用data进行填充
// 注意:resize在增多元素个数时可能会扩容
void TestVector3()
{
	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 contains:";
	for (size_t i = 0; i < v.size(); i++)
		cout << ' ' << v[i];
	cout << '\n';
}

// 测试vector的默认扩容机制
// vs:按照1.5倍方式扩容
// linux:按照2倍方式扩容
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';
		}
	}
}

// 往vecotr中插入元素时,如果大概已经知道要存放多少个元素
// 可以通过reserve方法提前将容量设置好,避免边插入边扩容效率低
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';
		}
	}
}

1.2.3vector增删查改

|------------------------------------------------------------------------------------------------|-------------------------------|
| vector增删查改 | 接口说明 |
| push_back(重点) | 尾插 |
| pop_back(重点) | 尾删 |
| find | 查找(注意这个是算法模块实现的不是vector的成员接口) |
| insert | 在position位置插入val |
| erase | 删除position位置的数据 |
| swap | 交换两个vector的数据空间 |
| operator[](重点) | 像数组那样访问数据 |

vector容器的增删查改代码演示:

cpp 复制代码
//  vector的增删改查

// 尾插和尾删:push_back/pop_back
void TestVector4()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	auto it = v.begin();
	while (it != v.end()) 
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	v.pop_back();
	v.pop_back();

	it = v.begin();
	while (it != v.end()) 
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

// 任意位置插入:insert和erase,以及查找find
// 注意find不是vector自身提供的方法,是STL提供的算法
void TestVector5()
{
	// 使用列表方式初始化,C++11新语法
	vector<int> v{ 1, 2, 3, 4 };

	// 在指定位置前插入值为val的元素,比如:3之前插入30,如果没有则不插入
	// 1. 先使用find查找3所在位置
	// 注意:vector没有提供find方法,如果要查找只能使用STL提供的全局find
	auto pos = find(v.begin(), v.end(), 3);
	if (pos != v.end())
	{
		// 2. 在pos位置之前插入30
		v.insert(pos, 30);
	}

	vector<int>::iterator it = v.begin();
	while (it != v.end()) 
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	pos = find(v.begin(), v.end(), 3);
	// 删除pos位置的数据
	v.erase(pos);

	it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

// operator[]+index 和 C++11中vector的新式for+auto的遍历
// vector使用这两种遍历方式是比较便捷的。
void TestVector6()
{
	vector<int> v{ 1, 2, 3, 4 };

	// 通过[]读写第0个位置。
	v[0] = 10;
	cout << v[0] << endl;

	// 1. 使用for+[]小标方式遍历
	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	vector<int> swapv;
	swapv.swap(v);

	cout << "v data:";
	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	// 2. 使用迭代器遍历
	cout << "swapv data:";
	auto it = swapv.begin();
	while (it != swapv.end())
	{
		cout << *it << " ";
		++it;
	}

	// 3. 使用范围for遍历
	for (auto x : v)
		cout << x << " ";
	cout << endl;
}
相关推荐
Miqiuha9 分钟前
装饰器设计模式学习
java·学习·装饰器模式
weixin_SAG38 分钟前
14天Java基础学习——第6天:面向对象编程(类与对象)
java·开发语言·学习
c_simplystudy41 分钟前
c++ 类和对象(中)
开发语言·c++·学习
钰爱&44 分钟前
【C】链表的创建、打印、插入、删除等
c语言·开发语言·数据结构·笔记·学习·链表
向上的车轮1 小时前
ODOO学习笔记(7):模块化架构(按需安装)
笔记·python·学习·架构·odoo
花姐夫Jun1 小时前
node.js学习笔记-Window下MongoDB数据库安装(二)
数据库·学习·mongodb·node.js
杨若瑜1 小时前
Go语言24小时极速学习教程(五)Go语言中的SpringMVC框架——Gin
学习·golang·gin
久恙5022 小时前
一文学会docker中搭建kali
运维·数据库·学习·网络安全·docker·容器
MogulNemenis3 小时前
每日八股——JVM组成
java·jvm·后端·学习