c++Primer——第九章:顺序容器

本文深入探讨C++标准库中的各种容器特性,包括迭代器、构造函数、array的使用及限制、赋值与swap操作的区别、assign成员的功能、emplace操作的优势、元素访问方式、随机访问的安全性、resize和reserve的作用等,并简要介绍了string的操作和容器适配器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、几个迭代器

begin、end、cbegin、cend、rbegin、rend、crbegin、crend

2、与顺序容器大小相关的构造函数

顺序容器(array除外)提供一个构造函数。它接受一个容器大小和一个(可选的)元素初始值,如果我们不提供元素的初始值,则标准库会创建一个值初始化器。如果元素类型是没有默认构造函数的类类型,则除了大小参数外,还必须指定一个显式的元素初始值。

3、标准库array

使用array必须同时指定元素类型和大小

	array<int, 3> arr;	//3个默认初始化的int
	array<int> arr1;	//错误  没有array<int>类型
	array<int, 3> arr2 = { 1,2,3 }; //列表初始化
	array<int, 3> arr3 = { 1 }; // 1,0,0

内置数组不能进行拷贝或对象赋值,但标准库array支持这种操作

	int a[3] = { 1,2,3 };
	int b[3] = a;		//错误 内置数组不支持拷贝或赋值
	array<int, 3> c = { 1,2,3 };
	array<int, 3> d = c; //正确

4、赋值和swap

赋值相关运算会导致指向左边容器内部的迭代器、引用、指针失效。而swap操作不会使他们失效。

5、assign

赋值运算符要求左右两边的运算对象具有相同的类型。顺序容器(除了array)还定义了一个名为assign的成员,允许我们从一个不同但相容的类型赋值,或者从一个容器的子序列赋值。assign也是拷贝

	list<string> sl;
	vector<const char*> cv;
	sl = cv;  // 错误 容器类型不匹配
	sl.assign(cv.begin(), cv.end()); //正确
	//也可以这样用
	sl.assign(10, "hi");

6、swap

swap操作交换两个相同类型的容器的内容。除array外,swap不对任何元素进行拷贝、删除或插入操作,因此可以保证在常数时间内完成。元素不会被移动的事实意味着除了string外,指向容器的迭代器、引用、指针在swap操作之后都不会失效,他们仍然指向swap交换前的元素,但是,着些元素已经属于不同的容器了。

7、emplace操作

emplace_fron、emplace、emplace_back是c++11新标准引入的成员,他们操作构造而不是拷贝元素。使用push或insert时是将元素类型的对象传递给它们,这些对象被拷贝到容器中,而调用emplace成员时,则是将参数传递给元素类型的构造函数

class A
{
public:
	A(int x, int y):a(x), b(y){}
	~A(){}

private:
	int a;
	int b;
};

void test()
{
	vector<A> vec;
	vec.emplace_back(1, 2);
	vec.push_back(A(1, 2));
}

10、访问元素

  • 包括array在内的每个顺序容器都有一个front成员函数
  • 除forward_list之外的所有顺序容器都有一个back成员函数
  • at和下标操作只适用于string、vector、deque和array

以上操作使用前都需要确保容器非空,它们都返回元素的引用。非const得情况下可以当左值使用。

11、下标操作和安全的随机访问

下标运算符并不检查下标是否在合法的范围内,使用越界的下标是一种严重的程序设计错误,编译器不检查这种错误。如果我们希望确保下标是合法的。可以使用at成员函数,使用at下标越界时会抛出out_of_range异常

	vector<int> vec;
	cout << vec[0] << endl; //运行时错误 vec中没元素
	cout << vec.at(0) << endl; // 抛出out_of_range异常

12、resize和reserve

    vector<int> ivec{ 5,3 };
	ivec.resize(10); //前5个3 后5个0
	cout << ivec.size() << " " << ivec.capacity() << endl;  // 10 10
	ivec.resize(3);	 //删除末尾的7个值  capacity不变
	cout << ivec.size() << " " << ivec.capacity() << endl;  // 3 10
	ivec.reserve(1);
	cout << ivec.size() << " " << ivec.capacity() << endl;  // 3 10
	ivec.reserve(8);
	cout << ivec.size() << " " << ivec.capacity() << endl;  // 3 10
	ivec.erase(ivec.begin());
	cout << ivec.size() << " " << ivec.capacity() << endl;  // 2 10
	ivec.shrink_to_fit();
	cout << ivec.size() << " " << ivec.capacity() << endl;  // 2 2

shrink_to_fit也只是个请求,标准库并不保证一定退还内存

13、string的诸多操作

14、容器适配器

标准库定义了三个顺序容器适配器:stack、queue和priority_queue

一个容器适配器接受一种已有的容器类型。使其行为看起来像一种不同的类型

默认情况下stack和queue是deque实现的,priority_queue是在vector上实现的。我们可以在创建一个适配器时将一个命名的顺序容器作为第二个类型参数来重载默认容器类型

	stack<string, vector<string>> str_stk; //在vector上实现的空栈
	stack<string, vector<string>> str_stk2(svec); //在vector上实现的栈,初始化时保存svec的拷贝

stack只要求push_back、pop_back、back操作,因此可以使用除array和forward_list外的任何容器类型来构造。queue要求back、push_back、front、push_front,因此可以构造与list或dqueu之上,但不能基于vector构造。priority_queue除了front、push_back、pop_back外还要求随机访问能力,因此可以用vector和deque构造,不能用list

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值