vector因为“容纳着”其他对象,所以也常常被称之为“容器”
一、vector基本内容
vector<int>ivec; //ivec保存int类型的对象
vector<Students>Student; //Student保存Students类型的对象
一方面,vector的优势在于,程序在运行的时候可以很高效地往vector对象中添加元素。
另一方面,vector还可以保存“类”的对象,这就很不错了
个人认为,vector的一大好处可以节约内存。就像我们在刚开始学C和C++的时候,若是要开一个数组,都是开类似于
int a[100000]={0};//开一个很大的值
//没错,但是很浪费内存,并且会让别人一看就发现是个新手小白
二、vector的初始化
vector<int>v1(10)//v1有10个元素,每个值都是0
vector<int>v2{10}//v2有1个元素,该元素的值是0
vector<int>v3(10,1);//v3有10个元素,每个值都是1
vector<int>v4{10,1}//v4有2个元素,分别为10和1
可知,()是用来初始化元素个数,{ }是用来初始化vector对象的
三、vector操作
```cpp
v.empty();//如果v不含任何元素,返回真;否则返回假
v.size();//返回v中元素的个数
v.push_back(t);//向v的尾端添加一个值为t的元素
v[n];//返回v中第n个位置上元素的引用
v1 = v2;//用v2中元素的拷贝替换v1中的元素
v1 = {a,b,c...};//用列表中元素的拷贝替换v1中的元素
注意:不能用下标形式添加元素
但可以队确知存在的元素执行下标操作,如:
vector<int> ivec;
cout << ivec[0];//错误:ivec不包含任何元素
vector<int>ivec2(10);
cout << ivec2[10];//错误:ivec2元素的合法检索是0-9
vector<int>c(10);
c[5] = 6;
cout << c[5] << endl;//输出结果是6,此可以说明课以在确定存在的元素执行下表操作
迭代器:
我们可以使用下标运算符来访问string对象的字符或vector对象的元素,其实还有另一种更通用的机制也可以实现同样的目的——迭代器。
迭代器有有效和无效之分,这一点和指针差不多
类似于指针类型,迭代器也提供了对对象的间接访问。但和指针不一样的是,获取迭代器不是选取地址符,有迭代器的类型同时拥有返回迭代器的成员。例如这些类型都有名为begin和end的成员,其中begin成员负责返回指向第一个元素的迭代器。
标准容器迭代器的运算符
*itera//返回迭代器iter所指元素的引用
iter->mem//解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter//令iter指示容器的下一个元素
--iter//令iter指示容器的下一个元素
!!因为end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用操作!
迭代器类型:
实际上那些拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型:
vector::iterator it; //it能读写vector的元素
string::iterator it2; //it2能读写string对象中的字符
vector::const_iterator it3; //it3只能读vector的元素,不能写元素
string::const_iterator it4; //it4只能读string对象中的字符,不能写字符
vector<int>c;
for (int i = 0;i < 10;i++)
{
c.push_back(i);
}
vector<int>::iterator it;
for (it = c.begin();it != c.end();++it)
{
cout << *it << endl;
}
输出结果是
0
1
2
3
……
9
这就是迭代器的用法了
结合解引用和成员访问操作
检查vector对象是否为空,可以用下面的代码
(it).empty();
其中圆括号必不可少,该表达式的含义是先对it解引用,然后解引用的结果再执行点运算符。
但为了简化上述表达式,c++语言定义了箭头运算符(->)箭头运算符把解引用和成员访问结合在一起,也就是说:
it->mem和(it).mem表达的意思相同。故也可以用it->empty();
例如
typedef struct node
{
int data;
struct node* next;
}stu;
stu* list1;
stu* list2;
void creat()
{
list1 = (stu*)malloc(sizeof(struct node));
list2 = (stu*)malloc(sizeof(struct node));
list1->next = NULL;//等价于(*list1).next = nullptr;
list2->next = NULL;//等价于(*list2).next = nullptr;
}
默写对vector对象的操作会使迭代器失效
vector可以动态的增长,但会有一些副作用。已知的一个限定是不能在范围内for循环想vector对象添加元素,还有一些限制后面会讲。
但凡是使用了迭代器的循环体,都不要向迭代器所属的容器中加元素
(例如push_back())操作。
关于c++primer练习3.26的一些见解
练习3.26:
在 100 页的二分搜索程序中,为什么用的是 mid = beg + ( end - beg ) / 2,而非 mid = ( beg + end ) / 2;?
答案很简单,因为在vector迭代器支持的运算中,不支持两个迭代器相加,但支持一个迭代器+(or)- 一个数值。
而两个迭代器相减就是它们之间的距离,是个数值!
学习资料:《C++Primer》,经典不愧是经典