c++标准库(c++ primer plus笔记)

目录

STL提供了一组表示容器、迭代器、函数对象和算法的模板。

1.模型类vector

模型类 array:

此上为笔记。 

2. 可对矢量执行的操作

 除分配存储空间外,vector模板还能做哪些呢?

什么是迭代器?

什么是超过结尾(past-the-end)呢?

push_back()是一个方便的方法,

erase()方法删除矢量中给定区间的元素。

insert()方法的功能erase()相反。


STL提供了一组表示容器、迭代器、函数对象和算法的模板。

(1.容器是一个与数组类似的单元,来存储数值

STL容器是同质的,即存储的数值类型相同;

(2.算法是完成特定任务的处方。(如排序查找)

(3.迭代器用来遍历容器的对象,类似于遍历数组的指针,是广义指针

(4.函数对象是类似于函数的对象,可以是类对象函数指针(有时函数名被用作指针)。

STL能够构造各种容器(包括数组、队列和链表)和执行各种操作(包括搜索、排序和随机排列)。

STL不是面向对象的编程,而是一种不同的编程模式——泛型编程(generic programming)。

1.模型类vector

本书4.10.1、4.10.2和4.10.3中笔记:

模型类vector类似于string类,也是一种动态数组

可在运行阶段设置vector对象的长度,可在末尾附加新数据,还可以在中间插入新数据

它是使用new创建动态数组的替代品

实际上vector类确实使用new和delete管理内存,但这种工作是自动完成的。

首先,要使用vector对象,必须包含头文件vector。其次,vector 包含在名称空间std中,因此可以使用using编译指令、using声明或std::vector。再次,模板使用不同的语法来指出它存储的数据类类型。最后,vector类使用不同的语法来指定元素数。

示例:

#include<vector>
...
using namespace std;
vector<int>vi;
int n;
cin>>n;
vector<double>vd(n);

其中,vi是vector<int> 对象,vd是一个 vector<double>对象。

由于vector对象在插入或添加时自动调整长度,因此可以将vi的初始长度设置为零

但要调整长度,需要使用vector包中的各种方法。

一般而言,下面的声明创建了一个名为vt的vector对象,它可以存储n_elem个类型为typeName的元素:
 

vector<typeName> vt(n_elem);

其中n_elem可以是整型常量,也可以是整形变量

模型类 array:

 vector类的功能比数组强大,但效率稍低。C++11中新增了模板类array,它也位于名称空间std中。

与数组由于,array对象的长度固定的,也是用栈(静态内存分配),而不是自由存储区,因此其效率与数组相同,但更方便安全。要创建array对象,需要包含头文件array。

array对象的创建语法与vector稍有不同。

#include<array>
...
using namespace std;
array<int,5>ai;
array<double,4>ad;

推而广之,下面的声明创建了一个名为arr的array对象,它包含n_elem个类型为typeName的元素:

array<typeName,n_elem> arr;

无论是数组、vector对象还是array对象,都可使用标准数组表示法访问各个元素。

其次,从地址可知,array对象和数组存储在相同的内存区域(即栈),而vector对象存储在另一个区域(自由存储区或堆)。

第三,可以将一个array对象赋给另一个array对象;而对于数组必须逐元素复制数据。

此上为笔记。 


继续进行16.3.1的笔记

计算中,矢量(vector)对应数组,而不是第11章介绍的数学矢量。

 计算矢量存储了一组可随机访问的值,即用索引直接访问其中的元素

所以vector类提供了与第14章介绍的valarray和ArrayTP以及第4章介绍的array类似的操作,即可以创建vector对象,对一个vector对象赋给另一个vector对象,使用 [ ] 运算符来访问vector元素

为了使vector类成为通用的,

 STL在vector头文件中定义了一个vector模板。

要创建vector模板对象,可使用通常的<type>表示法来指出使用的类型

另外vector模板使用动态内存分配,因此可以用初始化参数来指出需要多少矢量。

#include vector
using namespace std;
vector<int> ratings(5);  //a vector of  5 ints
int n;
cin>>n;
vector<double>scores(n);    //a vector of n doubles

由于 [ ] 运算符被重载,因此创建二次对象后,可以使用通常的数组表示法来访问各个元素:

rating[0]=9;
for(int i=0;i<n;i++)
    cout<<scores[i]<<endl;

分配器:

与string类相似,各种STL容器模板都接受一个可选的模板参数,该参数指定使用哪个分配器对象来管理内存。例如,vector模板的开头与下面类似:

template<class T,class Allocator =allocator<T>>
    class vector{...

如果省略该模板参数的值,则容器模板将默认使用allocator<T>,这个类使用new和delete。

//vect1.cpp -- introducing the vector template
#include<iostream>
#include<string>
#include<vector>

const int NUM=5; 
int main(){
	using std::vector;
	using std::string;
	using std::cin;
	using std::cout;
	using std::endl;

	vector<int> ratings(NUM);
	vector<string> titles(NUM);
	cout<<"You will do exactly as told.You will enter.\n"
		<<NUM<<"book titles and your ratings (0-10).\n";
	int i;
	for(i=0;i<NUM;i++){
		cout<<"Enter titles #"<<i+1<<":";
		getline(cin,titles[i]);
		cout<<"Enter Your rating (0-10):";
		cin>>ratings[i];
		cin.get(); 
	} 
	cout<<"Thank you.You entered the following:\n"
		<<"Rating\tBook\n";
	for(i=0;i<NUM;i++){
		cout<<ratings[i]<<"\t"<<titles[i]<<endl;
	}
	return 0;
}

 此处使用vector模板只是为方便创建动态分配的数组,下一节介绍一个更多类方法的例子。

2. 可对矢量执行的操作

 除分配存储空间外,vector模板还能做哪些呢?

所有的STL容器都提供了一些基本方法,包括size()——返回容器中元素数目swap()——交换两个容器的内容begin()——返回一个指向容器第一个元素的迭代器end()——返回一个表示超过容器尾的迭代器

什么是迭代器?

它是一个广义指针

实际上,也可以是指针,也可以是一个可对其执行类似指针的操作——如解除引用(如operator*())和递增(如operator++())——的对象。

通过将指针广义化为迭代器,让STL能够为各种不同的容器类(包括那些简单指针无法处理的类)提供统一的接口

每个容器类都定义了一个合适的迭代器,该迭代器的类型是一个名为iterator的typedef,其作用域为整个类

例如,要为vector的double类型规范声明一个迭代器,可以这么做:

vector<double>::iterator pd;//pd an iterator

假设scores是一个vector<double>对象:

vector<double> scores;

则可以使用迭代器pd执行这样的操作:

pd=scores.begin(); //have pd point to the first element
*pd=22.3;          //dereference pd and assign vallue to first element
++pd;              //make pd point to the next element

译:将pd指向第一个元素解除对pd的引用,并将值赋给第一个元素,将pd指向下一个元素

可知,迭代器的行为就像指针。

(C++11有自动类型推断:
不是

vector<double>::iterator pd=scores.begin();

而是

auto pd = scores.begin();    //C++11 automatic type deduction

什么是超过结尾(past-the-end)呢?

一种迭代器指向容器最后一个元素后面的那个元素。(类似于C语言字符串中字符后面的空字符   ‘/0’)只是空字符是一个,而“超过结尾”是一个指向元素的指针

end()成员函数标识超过结尾的位置。

如果将迭代器设置为 容器 的第一个元素,并且不断递增,则它最终将到达容器结尾,从而达到遍历整个容器的内容。

如果 scores 和 pd 的定义与前方的示例中相同,则可以用以下代码来展示显示(打印)容器的内容。

for(pd = scores.begin(); pd != scores.end(); pd++)
     cout << *pd << endl;

所有容器都包含刚才讨论的那些方法。vector模型类也包含一些只有某些STL容器才有的方法。

push_back()是一个方便的方法,

它将元素添加到矢量末尾。它将负责内存管理,增加矢量的长度,使之能容纳新的成员。即:

vector<double> scores;       //create an empty vector
double temp;
while(cin>> temp && temp >= 0)
    scores.push-back(temp);
cout<<"You entered "<< scores.size() << "scores.\n";

程序意义为,每次循环都给 scores 对象增加一个元素。

(在编写或运行程序时,无需了解元素的数目。只要有足够的内存,程序就可以根据需要增加scores的长度

erase()方法删除矢量中给定区间的元素。

他接受两个迭代器参数,这些参数定义了要删除的区间。

第一个迭代器指向区间的起始处,第二个指向区间的终止处的后一个位置

删除begin()和begin()+1指向的元素:

scores.erase(scores.begin(),socres.begin()+2);

 若it1和it2时迭代器,则STL文档使用[p1,p2)来表示从 p1 到 p2 (不包括p2)的区间。因此,区间[begin(),end()]将包括集合的所有内容。(只能出现在文档中)

insert()方法的功能erase()相反。

它接受3个迭代器参数,第一个参数指定了新元素的插入位置,第二个和第三个迭代器参数定义了被插入区间,该区间通常是另一个容器对象的一部分。

将矢量new_v中除第一个元素外的所有元素插入到old_v矢量的第一个元素前面:

vector<int> old_v;
vectoe<int> new_v;
...
old_v.insert(old_v.begin(),new_v.begin()+1,new_v.end());

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值