【C++】vector(上):vector的常用接口介绍(含迭代器种类的介绍)


前言

一、vector的介绍(包含vector类中typedef的部分类型别名介绍)
二、vector类的常用接口说明(vector类对象的 常见构造(重点)、容量操作、遍历操作 和 修改操作等接口,以及一些vector类非成员函数的接口)


一、vector的介绍

C++标准模板库中的容器vector是一个动态数组,能够自动管理内存,支持快速随机访问。 它的接口包括构造函数、大小和容量相关的操作、元素访问方法、修改容器的操作,还有迭代器相关的函数。
在这里插入图片描述

在C++标准库的 std::vector 中,allocator(内存分配器)是模板的第二个参数,通常可以忽略,使用默认的即可。但在需要特殊内存管理时,可以自定义allocator,不过这种情况相对少见。
默认内存分配器已足够高效,自定义内存分配器应仅在性能分析表明有必要时才会使用,所以后续介绍vector接口时,只会考虑大多数情况,忽略allocator(直接使用默认的)这个参数,简化vector的使用。

vector 类中typedef了很多类型别名,以下代码展示了一些常用的类型别名:

typedef T value_type;// 其中 T 是 vector 的第一个模板参数
typedef size_t size_type;
// size_t 是 C++ 标准库中定义的一个类型别名,它通常是一个无符号整数类型。其可能的定义方式如下:
// 64 位系统下: typedef unsigned long long size_t; 
// 32 位系统下: typedef unsigned int size_t; 
typedef T& reference;
typedef const T& const_reference;
typedef Allocator allocator_type;

二、vector的常用接口介绍

1.vector类对象的常见构造(含迭代器种类的介绍)

在这里插入图片描述
忽略allocator相关参数后的简化接口:

(constructor)构造函数声明接口说明
vector()无参构造,默认构造空容器
vector( size_type n, const value_type& val =value_type() )构造并初始化n个val
template< class InputIterator > vector ( InputIterator first, InputIterator last )使用迭代器进行初始化构造
vector (const vector& x)拷贝构造
vector ( initializer_list<value_type> il )初始化列表构造(C++11新增,了解用法)

示例一(无参构造,默认构造空容器):
vector( );

#include <vector>
using namespace std;

int main()
{
	vector<int> app;// size和capacity均为0
	return 0;
}

在这里插入图片描述
示例二(构造并初始化n个val):
vector( size_t n, const T& val = T( ) );

#include <vector>
#include <string>
using namespace std;

int main()
{
	vector<int> a1(5); // vector(size_t n, const int& val =int())
	vector<int*> a2(5); // vector(size_t n, const int*& val =int*())
	vector<int> a3(5, 10);

	vector<string> a4(5); // vector(size_t n, const string& val =string())
	vector<string> a5(5,"abcd");
	return 0;
}

在这里插入图片描述
在这里插入图片描述

补充:
(1)规定 int()、char() 等内置类型创建的匿名对象(不传参数时)默认为 0 ; int * ()、char * () 等默认为 nullptr
(2)string() 等自定义类型创建的匿名对象(不传参数时)会去调用对应的默认构造函数

示例三(使用迭代器进行初始化构造):
template< class InputIterator >
vector ( InputIterator first, InputIterator last );

#include <vector>
#include <list>
using namespace std;

int main()
{
	list<int> lst = { 1, 2, 3, 4, 5 }; // 初始化列表的构造方式
	vector<int> vec1(lst.begin(), lst.end());  // list的迭代器是双向迭代器

	int arr[] = { 4, 5, 6, 7, 8, 9 };
	vector<int> vec2(arr + 2, arr + 5);  // 指针作为随机访问迭代器

	vector<int> vec = { 10, 11, 12, 13, 14, 15 };
	vector<int> vec3(vec.begin() + 1, vec.end() - 2); // vector的迭代器是随机访问迭代器
	return 0;
}

在这里插入图片描述

补充知识(迭代器的种类)

在 C++ 中,迭代器(Iterator)是用于遍历容器(如 vectorlistmap等)中元素的对象,类似于指针的行为。根据功能强弱,迭代器分为以下 5 种类别,支持不同的操作:

(1). 输入迭代器(Input Iterator)

  • 功能:只能单向移动(向前),且只能读取元素(不可修改)。
  • 支持的操作++(前置/后置递增)、*(解引用)、==/!=(比较)。
  • 典型应用:一次性遍历(如从文件流读取数据)。
  • 示例istream_iterator(用于输入流)。

(2). 输出迭代器(Output Iterator)

  • 功能:只能单向移动(向前),且只能写入元素(不可读取)。
  • 支持的操作++(前置/后置递增)、*(解引用赋值)。
  • 典型应用:向容器或流中写入数据。
  • 示例ostream_iterator(用于输出流)。

(3). 前向迭代器(Forward Iterator)

  • 功能:继承自输入迭代器,支持多次读写和重复遍历。
  • 支持的操作:所有输入迭代器的操作,且可以多次递增。
  • 典型容器:单链表(如 forward_list)、哈希表(如 unordered_set)。

(4). 双向迭代器(Bidirectional Iterator)

  • 功能:继承自前向迭代器,支持双向移动(向前和向后)。
  • 支持的操作:所有前向迭代器的操作,新增 --(前置/后置递减)。
  • 典型容器:双链表(如 list)、关联容器(如 setmap)。

(5). 随机访问迭代器(Random Access Iterator)

  • 功能:功能最强,支持直接跳跃访问任意位置。
  • 支持的操作:所有双向迭代器的操作,新增:
    • +/-+=/-=(跳跃多个位置)。
    • [](下标访问)、比较大小(如 <, >)。
  • 典型容器:连续内存容器(如stringvectordeque、数组)。

迭代器关系图示
输入迭代器 → 前向迭代器 → 双向迭代器 → 随机访问迭代器(功能由低到高)
输出迭代器(独立分支)


关键区别

  • 随机访问迭代器效率最高(如 vector 的迭代器)。
  • 输入迭代器是等级最低的迭代器,所有更高级的迭代器(如前向、双向、随机访问迭代器)都兼容输入迭代器的功能。
  • 双向迭代器仅支持逐步移动(如 list)。
  • 算法需根据迭代器类型选择实现(如 算法库中的sort 需要随机访问,而list的双向迭代器不能满足sort随机访问的要求,所以list 需用自己的 sort 方法)。

示例四(拷贝构造):
vector (const vector& x);

#include <vector>
using namespace std;

int main()
{
	vector<int> vec = { 10, 11, 12, 13, 14, 15 }; 
	vector<int> vec1(vec); // 用vec拷贝构造vec1
	return 0;
}

在这里插入图片描述
示例五(初始化列表构造):
vector ( initializer_list< T > il );

#include <vector>
#include <string>
using namespace std;

int main()
{
	vector<int> vec1{ 1, 2, 3 }; // 调用初始化列表构造vector对象时要使用花括号
	vector<string> vec2{ "hello", "world" };

	vector<int> vec3 = { 5, 6, 7 };
	return 0;
}

在这里插入图片描述

2.vector iterator 的使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接口功能
begin获取第一个数据位置的iterator/const_iterator
end获取最后一个数据的下一个位置的iterator/const_iterator
#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> s1 = { 1,3,5,7,9 };
	vector<int>::iterator it1 = s1.begin();
	// 普通vector对象调用 iterator begin();
	// 返回指向vector对象中第一个元素的普通迭代器,允许修改vector对象中的元素
	while (it1 != s1.end())
	{
		(*it1)++;
		cout << *it1 << ' ';
		++it1;
	}
	cout << endl;

	const vector<int> s2 = { 1,3,5,7,9 };
	vector<int>::const_iterator it2 = s2.begin();
	// const vector对象调用 const_iterator begin() const;
	// 返回指向const vector对象第一个元素的const迭代器,只允许读取const vector对象中的元素,不能修改
	while (it2 != s2.end())
	{
		cout << *it2 << ' ';
		++it2;
	}
	cout << endl;
	return 0;
}

在这里插入图片描述

3.vector类对象的容量操作

在这里插入图片描述

3.1 size、capacity 和 empty的使用

接口功能
size获取数据个数
capacity获取容量大小
empty判断是否为空

(1)size 和 capacity

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> vec1{ 1,2,3,4,5 };
	cout << "vec1的有效数据个数:" << vec1.size() << endl;
	cout << "vec1的容量:" << vec1.capacity() << endl;

	vector<int> vec2{ 6,6,6,6,6,6,6,6,6,6,6};
	cout << "vec2的有效数据个数:" << vec2.size() << endl;
	cout << "vec2的容量:" << vec2.capacity() << endl;
	return 0;
}

在这里插入图片描述

(2)empty

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> vec1{ 1,2,3,4,5 };
	cout << "vec1是否为空:" << vec1.empty() << endl;

	vector<int> vec2;
	cout << "vec2是否为空:" << vec2.empty() << endl;
	return 0;
}

在这里插入图片描述

3.2 reserve的使用

在这里插入图片描述
std::vector 类提供的 reserve() 成员函数,用于请求vector对象的容量调整。
注:这个函数不会改变vector对象的有效数据个数,也不会修改vector对象有效数据中的内容。

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
	cout << "v1的有效数据个数:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;

	v1.reserve(50);

	cout << "v1的有效数据个数:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;
	return 0;
}

在这里插入图片描述
我们一般只用reserve函数进行扩容,使用场景如下:在你预先知道vector对象将增长到某个大小时,可以使用reserve函数提前分配足够的空间,避免频繁扩容。

3.3 resize的使用

在这里插入图片描述
std::vector类提供的 resize() 成员函数,用于改变有效数据个数。
如果新的个数大于当前个数,会新增有效数据个数,新增元素初始化为 val;如果新的个数小于当前个数,减少有效数据个数。

示例一(新的个数大于当前个数,会新增有效数据个数,新增元素初始化为 val):

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3 };
	cout << "v1的有效字符长度:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;

	v1.resize(5, 10);
	cout << "v1的有效字符长度:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;

	v1.resize(10, 100);
	cout << "v1的有效字符长度:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
示例二(新的个数小于当前个数,减少有效数据个数):

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
	cout << "v1的有效字符长度:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;

	v1.resize(5);

	cout << '\n' << "v1的有效字符长度:" << v1.size() << endl;
	cout << "v1的容量:" << v1.capacity() << endl;
	return 0;
}

在这里插入图片描述

4.vector类对象的访问(包含data:返回底层数组的指针)

在这里插入图片描述

接口功能
operator[]返回n位置的数据(越界访问的情况是不确定的)
at()返回n位置的数据(越界访问会抛异常)
data()返回底层数组的指针(C++11)

(1)operator[]
在这里插入图片描述

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{1,2,3,4,5,6,7,8,9};
	for (size_t i = 0; i < v1.size(); ++i)
	{
		v1[i] += 1;
		cout << v1[i] << ' ';
		// 普通对象调用 int& operator[](size_t n); 
		// 返回vector对象中指定位置数据的引用(int&),
		// 这意味着你可以通过返回的引用修改数据的内容。
	}
	cout << endl;

	const vector<int> v2{ 1,2,3,4,5,6,7,8,9 };
	for (size_t i = 0; i < v2.size(); ++i)
	{
		cout << v2[i] << ' ';
		// const对象调用 const int& operator[](size_t n) const; 
		// 返回vector对象中指定位置数据的常引用(const int&),
		// 这意味着你只能读取vector对象中的数据,而无法进行修改。
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
(2)at( )
在这里插入图片描述

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{1,2,3,4,5,6,7,8,9};
	for (size_t i = 0; i < v1.size(); ++i)
	{
		v1.at(i) += 1;
		cout << v1.at(i) << ' ';
		// 普通对象调用 int& at(size_t n); 
		// 返回vector对象中指定位置数据的引用(int&),
		// 这意味着你可以通过返回的引用修改数据的内容。
	}
	cout << endl;

	const vector<int> v2{ 1,2,3,4,5,6,7,8,9 };
	for (size_t i = 0; i < v2.size(); ++i)
	{
		cout << v2.at(i) << ' ';
		// const对象调用 const int& at(size_t n) const; 
		// 返回vector对象中指定位置数据的常引用(const int&),
		// 这意味着你只能读取vector对象中的数据,而无法进行修改。
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
(3)data( )
在这里插入图片描述

#include <vector>
#include <iostream>
using namespace std;

int main()
{
    std::vector<int> myvector(5, 10);
    cout << "myvector contains:";
    for (unsigned i = 0; i < myvector.size(); ++i)
    {
        cout << ' ' << myvector[i];
    }
    cout << '\n';

    int* p = myvector.data();
    *p = 20;
    ++p;
    *p += 20;
    p[2] = 100;

    cout << "myvector contains:";
    for (unsigned i = 0; i < myvector.size(); ++i)
    { 
        cout << ' ' << myvector[i];
    }
    cout << '\n';
    return 0;
}

在这里插入图片描述

5.vector类对象的修改操作

在这里插入图片描述

5.1 push_back、insert(插入数据)

接口功能
push_back在末尾插入一个元素
insert在迭代器 position 位置插入元素

(1)push_back
在这里插入图片描述

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,1,1,1,1,1,1,1 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	v1.push_back(100); // 尾插一个元素

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述

(2)insert
在这里插入图片描述
示例一(插入多个相同元素):
iterator insert(const_iterator pos, size_t count, const T& val);

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,1,1,1,1,1,1,1 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	v1.insert(v1.begin() + 5, 3, 10);

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述

示例二(插入范围元素):
template < class InputIterator >
iterator insert(const_iterator pos, InputIterator first, InputIterator last);

#include <vector>
#include <list>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,1,1,1,1,1,1,1 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	list<int> lst{ 10,11,12,13,14,15 };
	v1.insert(v1.begin() + 5, lst.begin(), lst.end());  // list的迭代器是双向迭代器

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述

示例三(插入初始化列表):
iterator insert(const_iterator pos, initializer_list< T > il);

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,1,1,1,1,1,1,1 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	v1.insert(v1.begin() + 5, { 9,5,2,7 }); // 插入初始化列表

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述

5.2 pop_back、erase 和 clear(删除数据)

接口功能
pop_back删除末尾元素
erase删除迭代器 pos 指向的元素
clear清空所有有效元素(不释放内存)

(1)pop_back
在这里插入图片描述

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	v1.pop_back();

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述

(2)erase
在这里插入图片描述
示例一(删除单个元素):

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	v1.erase(v1.begin() + 5); // 删除第6个元素

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述
示例二(删除范围元素):

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';

	v1.erase(v1.begin() + 5, v1.end() - 1); //删除第6~8的元素

	for (unsigned i = 0; i < v1.size(); ++i)
	{
		cout << ' ' << v1[i];
	}
	cout << '\n';
	return 0;
}

在这里插入图片描述

(3)clear
在这里插入图片描述

#include <vector>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
	v1.clear();
	return 0;
}

在这里插入图片描述
在这里插入图片描述

5.3 成员函数swap

swap成员函数是用于高效交换两个vector对象的内容的函数
在这里插入图片描述

#include <vector>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3};
	vector<int> v2{ 10,20,30,40 };
	v1.swap(v2);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

6.vector类非成员函数

在这里插入图片描述

6.1 relational operators系列函数

在这里插入图片描述

#include <vector>
using namespace std;

int main() 
{
    vector<int> v1{ 1,2,3 };
    vector<int> v2{ 1,2,3,4 };
    vector<int> v3{ 1,3,2 };

    // == 运算符:元素数量相同且对应元素相等
    bool b1 = (v1 == v2);  // false(元素数量不同)

    // != 运算符:存在至少一个不相等元素
    bool b2 = (v1 != v3);  // true(在第二个元素 2 != 3)

    // < 运算符:字典序比较,遇到第一个不同元素时判断
    bool b3 = (v1 < v2);   // true(v1是v2的前缀)
    bool b4 = (v1 < v3);   // true(在第二个元素 2 < 3)

    // > 运算符:字典序更大
    bool b5 = (v2 > v3);   // false(在第二个元素 2 < 3)
    return 0;
}

在这里插入图片描述

核心原理

  1. 字典序比较

    • 逐个元素对比,直到发现不相等的元素
    • 若一个vector是另一个的前缀,较短的vector更小
    • 元素必须支持operator<(自定义类型需重载)
  2. 类型一致性

    • 只能比较相同类型的vector(vector<int>不能与vector<double>比较)

6.2 非成员函数swap

std::vector的非成员函数swap专门用于交换两个同类型std::vector对象。它底层实际上调用了std::string的swap成员函数。
它在功能上与std::vector的swap成员函数完全一致,但其提供了更为通用的接口。

在这里插入图片描述

#include <vector>
using namespace std;

int main()
{
	vector<int> v1{ 1,2,3};
	vector<int> v2{ 10,20,30,40 };
	swap(v1, v2); // 功能上与std::vector的swap成员函数完全一致,但其提供了更为通用的接口
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值