网站无法被百度收录,商丘专业做网站公司,苏州公司网站建设方案,营销新闻一、引言
在C语言中#xff0c;不论是数组#xff0c;还是结构体定义的数组#xff0c;功能都比较欠缺#xff0c;不是单纯的添加几个变量就能够解决的。缺少增删查改的功能#xff0c;为了解决这个问题#xff0c;C决定填上C语言这个坑#xff0c;但是填过坑的人都知道…一、引言
在C语言中不论是数组还是结构体定义的数组功能都比较欠缺不是单纯的添加几个变量就能够解决的。缺少增删查改的功能为了解决这个问题C决定填上C语言这个坑但是填过坑的人都知道想填一个坑必定需要在其他地方挖一个坑。这些坑呢零零碎碎等遇到我们再一一揭晓。C的祖师爷本贾尼博士创造了vector这一容器既然vector是容器那它必然可以包含各种各样的数据。很多东西都具有相似性容器本身就是要将相似的物品归位一类。这里需要用到一个模板的工具。 二、 vector的大概介绍相当于数组依照先后顺序排列
vector是STL的六大组件之一头文件vector与之前string不同的是vector的增删查改使用迭代器特别频繁。主要是基于迭代器的灵活性、适配性、安全。vector还有个别名是顺序表(sequence list)至于它为什么叫vector(向量)就不得而知了。既然有顺序表这个别名那vector肯定与顺序表有着千丝万缕的联系实际上vector的底层就是顺序表。在使用过程中记得按需实例化模版的内容。
三、模版template
模版本身可以理解为一个模具分为函数模版和类模版只要符合的内置类型计算机规定的类型或自定义类型都可以套用模版编译器会根据函数模版或是类模版生成一个对应的函数或类有多少种不同的类型就会生成多少个模版就像方程组中的未知量直到编译时模板才会被编译器替换为准确类型就像我们求方程时求x的大小一样算一遍才会得出x的值。编译器也会根据接受到的变量类型或根据使用者的按需实例化将模版类型替换。遇到不同类型使用模版编译器也会生成不同类型的函数和类这样我们就可以将不同的类型复用在同一段代码上了大大增加了代码的复用性节省了时间。
//class和typename都可以用来定义模版类型
templateclass 自定义的类型名,typename 自定义的类型名//vector的使用
std::vectorint /*按需实例化编译器自动将模版类型替换该类型*/ v(初始化值);
//没有初始化值时不需要加()不然编译器分不清这是函数还是类对象。//最好的初始化是使用{}花括号这样编译器默认只是一个变量
//当然{}中可以像数组那样写出多个值。
std::vectorint v{ };
std::cout v[0] std::endl;
当然模版类型也可以给缺省参数。也就是给定一个确定的类型。如果没有类型的传入编译器根据缺省参数生成一个确定的类型。
//class和typename在tmeplate的声明中是一样的混着用都没关系
templateclass T,class T1 int
//
templatetypename T,typename T2 double 3.1函数模版 函数模版即在函数的形参的类型与类模版不同的是他可以不需要按需实例化因为函数只有在执行可执行文件时才会建立栈帧。而类模版则不同在没有缺省参数时需要按需实例化。
templateclass T
void swap(T tmp1,T tmp2)
{T tmp tmp1;tmp1 tmp;tmp2 tmp;
}int main()
{int a 11 , b 13;swapint(a , b);return 0;
} 3.2类模版 类的声明就和内置类型一样需要开好空间如果连类型都不确定还怎么计算内存开空间呢哪怕是一个空类也有一字节的空间。因为编译器还会根据类的地址来查找类中的函数。这就需要类的声明的做好按需实例化。
四、 vector的详细介绍 4.1 vector中的迭代器 vector类中虽然的很多函数都会使用迭代器。即是因为迭代器方便实用又是因为要与其他的STL组件接轨。迭代器与指针相似但有些迭代器可能不是指针可能是用类封装这个以后有机会再讲。 在vector中的迭代器分为正向迭代器和反向迭代器。正向迭代器(iterator)、反向迭代器(reverse_iterator)。顾名思义正向迭代器是由顺序表起始位置(begin())到最后一个位置的的下一个位置(end())反向迭代器就是从最后一个位置(rbegin())到顺序表的起始位置的下一个位置(rend())可以通过解引用操作符访问自然也可以通过解引用操作符修改值。(除const迭代器以外)
#includeiostream
//vector的头文件
//为了与C语言作区分不加.h后缀
#includevectorint main()
{std::vectorint v;//尾插一个数据v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);std::vectorint::reverse_iterator it v.rbegin();while (it ! v.rend()){std::cout *it ;it;}//不可访问end()、rend(()函数都是从//std::cout *(v.end()) std::endl;//不论是reverse_iterator还是iterator//都是从正向或是反向的位置相加、减前置后置加加、减减。std::vectorint::reverse_iterator it v.rbegin();while (it ! v.rend()){std::cout *it ;it;}//std::cout *(v.end()) std::endl;return 0;
}
const迭代器只能访问不能修改值。const迭代器直接往迭代器前加const_直接const在迭代器前加const则会报错不管迭代器的底层都是否为指针它都是一个对访问方式的封装并不是一个单纯的类型。
//初始化当然也可以不加小括号直接就大括号
std::vectorint v({1,2,3,4,5,6});std::vectorint::const_iterator it v.begin();
while (it ! v.end())
{std::cout *it ;it;
} 4.2 vector中的尾插函数 push_back()和string中的push_back()效果相差无几都是往最后的位置插入类型元素。至于是什么类型就看声明时按需实例化的是什么类型。当然它也可以用来存储char类型。也可以按需实例化成string。
//这里用int类型做个示范
vectorint v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);//这里用string做一个示范
vectorstring vs;
vs.push_back(ABC);
vs.push_back(ABC);
vs.push_back(ABC);
vs.push_back(ABC); 4.3vector中的insert和erase函数 vector中的在指定位置插入和在删除指定位置。这里需要注意的是此insert、erase非string中的insert、erase。需要用迭代器这里用迭代器自然是为了和STL的其他容器保持一致。但是至少也要重载一个下标插入、删除所以C某些设计还是不完善。
C11的官网cplusplus.com - The C Resources Network
C11vector中的insertvector::insert - C Reference (cplusplus.com)
C11vector中的erasevector::erase - C Reference (cplusplus.com)
std::vectorint v{ 1,3,4 };
v.insert(v.begin() 1, 2);
//注意迭代器失效的问题
for (auto e : v)
{std::cout e ;
}
std::cout std::endl;
//注意end()、rbegin()都是顺序表之外的位置
//end()是末尾位置的下一个位置。
//rbegin()是开头的上一个位置。
v.erase(v.end() - 1);
for (auto e : v)
{std::cout e ;
}
用迭代器访问时注意insert()后迭代器位置就已经失效了需要更新一下这里原因是扩容导致的。因为内存上的堆区也并不是所有位置都可以访问的也有些是无法访问的我们要保证顺序表的连续性只能另寻他处再复制拷贝下来。
//迭代器更新insert会自动返回插入位置的迭代器
std::cout std::endl;
std::vectorint v1{ 1,3,4 };
std::vectorint::iterator it v1.begin() 1;
it v1.insert(it, 2);
while (it ! v1.end())
{std::cout *it ;it;
}//错误示例 std::cout std::endl;std::vectorint v1{ 1,3,4 };std::vectorint::iterator it v1.begin() 1;v1.insert(it, 2);while (it ! v1.end()){std::cout *it ;it;} 4.4vector的下标访问 和string一样vector也可以用下标来访问。这里size()和capacity()就不讲了string中讲过了。
std::vectorint v{ 1,3,4 };
for(int i 0;i v.size();i)
{std::cout v[i] ;
} 4.5vector拷贝构造和operator 这是我们比较容易忽略的。顺嘴提醒一下。
std::vectorint v{ 1 , 2 , 3 , 4 }
std::vectorint v1 v;