Th2.8:vector类型详述

本博客将记录:vector类型这个知识点的笔记!    

今天总结的知识分为3个点:

   一、vector类型简介
   二、定义和初始化vector对象(只介绍日常coding中最常用的几种)
   三、vector对象上的操作(只介绍最常用的几种,其他的用到再翻书orBaidu即可)
   补充:对范围for这个知识点的进一步讲解

   一、vector类型简介:

        vector是标准库提供的一种动态数组容器可以把若干的同类型的对象or变量放在里面。

有2个要注意的点:

        1)使用时要包含头文件<vector>

#include<vector>

        2)定义vector容器对象的格式:

vector< Original or Self-define dataTypeName> vectorObjectName;
比如:

vector<int> vec;//定义了一个存放int内置数据类型的动态数组(vector容器的对象)
vector<Person> vec;//定义了一个存放Person自定义数据类型的动态数组(vector容器的对象)
vector< vector<int> > vec;//容器套容器,这其实就相当于定义了一个二维数组的意思
(但一般来说不推荐这样容器套容器的用法)

vector<TreeNode* > vec;//vec中每一个元素都是TreeNode*类型的数据

<里面存放的是啥类型的对象or数据> 就认为是vector中存放的数据
因为标准库中vector的源码是函数模板
<int>其实就是类模板的实例化的过程
也即:
template<typename T> T就是vector中存放的数据的类型
vector<T> vec;
......

注意:不能往vector中放引用类型,因为引用类型就是给别的数据or对象起一个别名而已,本质上并不是对象!

vector<int&> vec;//×!!!引用类型不能放入容器中

   二、定义和初始化vector对象(只介绍日常coding中最常用的几种):

1)空vector对象:

vector<string> myStr;//创建了一个空的vector容器的对象

2)元素拷贝的初始化vector:

vector<string> myStr2(myStr);
//这个拷贝过程其实先创建一个存储myStr数据的临时匿名对象,再将这个你们对象拷给myStr2
vector<string> myStr3 = myStr;
//直接进行拷贝赋值

3)C++11标准引入的初始化vector的方式:列表初始化,即:用{ }括号括起来

vector<int> vec {1,3,5,7,9,};
//这和 C++11引入的 int a[] {1,3,5,7,9,}的初始化方式是同理的
vector<int> vec2 {vec} ;
//直接将vec拷贝复制给vec2

4)创建指定容器对象的元素数量的初始化vector方式:

(但凡碰到设置元素数量时候,一般都会用到圆括号)

vector<int> vv(5, 1001);
//给vector容器对象vv创建5个int型的元素,且每一个元素的值都是1001

//打印输出vv
//包含<algorithm>头文件并写一个仿函数print打印int型数据
for_each(vv.begin(), vv.end(), print());
cout << endl;

//当然,你也可以不给初始值,而只是指定容器的size
vector<int> vv(5);
//给vector容器对象vv创建5个int型数据,其中每个数据默认初始值为0
vector<string> vStr(3);
//给vector容器对象vStr创建3个string型数据,其中每个字符串默认初始值为空串""

5)多种初始化vector的方式:

vector<int> v1(10);//创建了一个v1对象,存储了10个int型元素,每个元素的默认初始值为0
vector<int> v2{10};//创建了一个v2对象,存储了一个data为10的int型元素

vector<int> v3(10,1);//10个元素,每个元素的值为1
vector<int> v4{10,1};//2个元素,分别是v4[0] == 10,v4[1] == 1

vector<string> vStr1{ "hello" };//创建要给vStr1对象,其存储了一个"hello"元素
//不提倡这么写,这样写很诡异了!
vector<string> vStr2{10};
//10不为string类型,因此无法通过初始化列表的方式来初始化vStr2
//因此有:
// {}-->退化为(),10不可以作为string类型对象的内容
//这就相当于创建了一个vStr2对象,其size为10的,每个string元素的默认初始值都是空串""

vector<string> vStr3{10,"hello,world!"};//诡异写法
<===>
vector<string> vStr4(10,"hello,world!");//这才是正规的写法
//含义:都是创建了一个vStr3对象,包含10个string类型的元素,每个元素的值都为"hello,world!"

总结:要想正常通过{}大括号给vector对象初始化,那么{}内的值类型必须与vector后的这个<>里边的类型一致。   

三、vector对象上的操作(只介绍最常用的几种):
       
对于vector容器,我们最常用的是:事先未知vector里有多少个元素,so我们需要有对vector容器对象动态增加or减少的成员函数(方法),so我们先创建空的vector再对其do一些操作。


1)判断是否为空.empty(),返回的是布尔值(bool,true就是真,false就是假)

vector<int> vecc;
if(vecc.empty()) cout<<"vecc为空!"<<endl;

 

 2).push_back():常用方法,用于向vector中的末尾增加(push)一个元素

vector<int> vecc;
vecc.push_back(1);
vecc.push_back(2);
vecc.push_back(3); 

 

  3).size():常用方法,用于求vector中的元素个数

//输出上述vecc容器对象的size
cout << vecc.size() << endl;//vecc.size() == 3

   4).clear():常用方法,用于清空vector中的all的元素

vecc.clear();//清空
//再输出上述vecc容器对象的size
cout << vecc.size() << endl;//vecc.size() == 0,因为clear清空了

   5)vector[n]:常用方法,用于返回vector容器对象中的index == n 的这个元素,注意,位置是从0开始的,这和数组的用法一模一样

(当然,如果index <0 || index >= vector.size()的话,返回的值就是一个不可预测的结果)

vector<int> vec{1,3,5,7};
for(int i=0;i<vec.size();i++){cout<<vec[i]<<"\t";}
cout<<endl;

    6) vec1 = vec2; 等号赋值(vector容器中是重载了operator=号的)

vector<int> vec1{1,3,5,7};
vector<int> vec2;//vec2为空
vec2.push_back(111);//vec2--> {111}
vec2 = vec1;//vec2--> {1,3,5,7}
vec2 = {8,8,9,9,10};//vec2--> {8,8,9,9,10}
cout<<vec2.size()<<endl;//vec2.size() == 5

  7) ==  等于号!= 不等于号 。(vector容器中是重载了operator==号和operator!=号)

所谓的vector相等:容器对象中的元素的个数相同对应位置的元素也相同

同时满足这2条件才叫相等,否则就是不相等。

//仍然拿上述的vec2和vec容器对象作判断
bool ret1 = (vec2 == vec) ? true : false;//ret == false
bool ret2 = (vec2 != vec) ? true : false;//ret == true

  8)vector的范围for的应用(和string对象类似)

  当你做范围for遍历容器vec中的每一个元素时,想对其元素进行修改,那么就正常用auto即可

(此时是把vec中的元素都赋值一份给到x)

vector<int> vec{1,3,5,7};
for(auto x:vec){cout<<x<<"\t";}//x就代表当前循环所遍历到的vec中的元素的值
cout<<endl;

 

 当你做范围for遍历容器vec中的每一个元素时,想对其元素进行修改,那么就要用到auto&这种引用的方式了,当然对于这里的vector<int>vec 你可以用 int&,一般我们用auto&让系统进行自动类型推断即可了。(此时是把x指向vec中的元素的地址了,因为取了别名,占据相同的内存空间,因此可以do修改)

vector<int> vec{1,3,5,7};
for(auto& x:vec){
    cout<<"Before revising:"<<endl;
    cout<<x<<endl;
    x = 8;
    cout<<"After  revising:"<<endl;
    cout<<x<<endl;
}
cout<<endl;

    补充:对范围for这个知识点的进一步讲解:

其实,本质上范围for语句是拿来对于某个序列do遍历(把序列中all的元素都搜素一遍,就叫做遍历)的,使用时对于序列本身而言是固定了的,如果说你此时再添加or减少序列的元素的话,就会导致输出彻底乱套!

就像下面注释了的这行坑爹代码千万不要写!

for (auto x : vec) {
	//vec.push_back(788);//这行会导致输出彻底乱套!
	cout << x << endl;
}
或者
for (int i = 0;i < vec.size();i++) {
	//vec.push_back(788);
    //这行会导致输出死循环因为每一次都push一个元素,导致拥有无法遍历输出完vec中的元素
	cout << vec[i] << endl;
}

 这里直接给结论:在for语句中(遍历一个容器等类似操作时),千万不要改动vector容器的容量size,也即你在这个过程对vector进行增加or删除的操作,千万不要这么干!否则你会很容易因为找不出错误而烦恼!!!

 好,那么以上就是这一2.8小节我所回顾的内容的学习笔记,希望你能读懂并且消化完,也希望自己能牢记这些小小的细节知识点,加油吧,我们都在coding的路上~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fanfan21ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值