文化传媒 网站设计,wordpress登记打印,成都企业建站系统模板,网站建设用阿里云的虚拟主机目录 1. C/C中的数组
1.1. C语言中的数组
1.2. C中的数组 2. vector的接口
2.1. vector的迭代器
2.2. vector的初始化与销毁
2.3. vector的容量操作
2.4. vector的访问操作
2.5. vector的修改操作 #x1f493; 博客主页#xff1a;C-SDN花园GGbond ⏩ 文章专栏…
目录 1. C/C中的数组
1.1. C语言中的数组
1.2. C中的数组 2. vector的接口
2.1. vector的迭代器
2.2. vector的初始化与销毁
2.3. vector的容量操作
2.4. vector的访问操作
2.5. vector的修改操作 博客主页C-SDN花园GGbond ⏩ 文章专栏玩转c 1. C/C中的数组
1.1. C语言中的数组
在 C 语言中数组是一组相同类型元素的有序集合。与字符串类似它的大小在编译时就已经确定不可更改。
//大小为5的整型数组
int arr1[5] { 1,2,3,4,5 };
//大小为5的浮点型数组
double arr2[5] {0.0};1.2. C中的数组
同样与string类似C为了更加方便就引入了一个支持可动态大小数组的序列容器vecotr。其特点如下 vector是可变大小的序列容器采用连续存储空间存储元素可通过下标高效访问。与数组不同vector大小可动态改变由容器自动处理。vector本质上用动态分配数组存储元素插入新元素时可能重新分配空间即分配新数组并移动全部元素此操作时间代价高但不是每次插入都重新分配。vector会分配额外空间适应增长不同库策略不同但重新分配通常是对数增长间隔使末尾插入元素能在常数时间完成。与deque、list和forward_list相比vector访问元素及末尾添加和删除元素更高效非末尾的删除和插入操作效率低且统一的迭代器和引用更好。 //整型数组
vectorint v1;
//浮点型数组
vectordouble v2;使用vector都需要包含头文件#includevector。并且vector是一个模版类所以在使用时需要显示实例化。 2. vector的接口
介绍一些vector的常见接口因为很多接口的作用都与string的接口非常类似所以很多就不在详细说明具体也可以参考vector文档。 下面我们开始研究他的使用为了能够更好的测试我们先实现一个打印容器元素的函数vector底层是数组所以有三种访问方式下标访问、迭代器访问、范围for本质也是迭代器
void Printf(vectorint v)
{//下表遍历cout 下表遍历;for (size_t i 0; i v.size(); i){cout v[i];}cout endl;//迭代器遍历cout 迭代器遍历;vectorint::iterator it v.begin();while (it ! v.end()){cout *it;it;}cout endl;cout 范围for遍历;for (auto e : v){cout e;}cout endl;
}
int main()
{vectorint v { 1,2,3,4,5,6,7,8,9 };Printf(v);//Test01();return 0;
}
2.1. vector的迭代器
同样的vector中也存在迭代器iterator因为定义在vector类中所以其需要通过域作用限定符访问——vector类型::iterator
下面将介绍的begin()end()rbeign()rend()的使用访问方法与string中的几乎一摸一样我们直接上实例演示
#includeiostream
#includevectorusing namespace std;
void Test01()
{vectorint v { 1,2,3,4,5,6,7,8,9 };cout 顺序遍历:;vectorint::iterator it v.begin();while (it ! v.end()){cout *it;it;}cout endl;cout 逆序遍历:;vectorint::reverse_iterator rit v.rbegin();while (rit ! v.rend()){cout *rit;rit;}cout endl;}
int main()
{Test01();return 0;
} 当然vector也支持const_iterator用法也类似这里就不在赘述。
2.2. vector的初始化与销毁 1 空容器构造函数默认构造函数 构造一个没有元素的空容器。 2 填充构造函数 构造一个包含n个元素的容器。每个元素都是val的副本。 3 范围构造器 构造一个包含与范围[firstlast一样多的元素的容器每个元素都按照相同的顺序从该范围内的相应元素构造而成。 4 复制构造函数 构造一个容器其中包含x中每个元素的副本顺序相同。 同样的vector也支持多种构造函数拷贝构造以及赋值运算符重载。
void Test02()
{//无参构造vectorint v1;Print(v1);//有参构造n个位置初始化vectorint v2(5, 2);Print(v2);//有参构造n个位置调用T类型的默认构造vectorint v3(5);Print(v3);//拷贝构造vectorint v4(v3);Print(v4);//迭代器区间构造(传string的迭代器区间)string s(hello world);vectorint v5(s.begin(), s.end());Print(v5);//迭代器区间构造(传vctor的迭代器区间)vectorint v6(v5.begin(), v5.end());Print(v6);//赋值重载v1 v6;cout v1 v6 endl;//深拷贝Print(v1);//特殊的赋值方式vectorint v7{ 1,2,3,4,5,6,7,8 };Print(v7);
} 2.3. vector的容量操作 在vector类中同样可以通过size()容器的有效长度capacity()返回容器的容量大小。
void Test03()
{vectorint v1;cout v1.size() endl;cout v1.capacity() endl;vectorint v2 { 0,1,2,3,4,5 };cout v2.size() endl;cout v2.size() endl;
} 在初始化时vecotr中的size与capacity一般相同。这时我们也可以通过以下程序探究一下其扩容机制
void Test04()
{size_t sz;vectorint v;sz v.capacity();cout making v grow endl;for (int i 0; i 100; i){v.push_back(i);if (sz ! v.capacity()){sz v.capacity();cout capacity changed v.capacity() endl;}}
}
int main()
{Test04();return 0;
} 在VS环境下vector一般是以1.5倍扩容。但是在Linux环境下一般就以2倍扩容。 要求容器减少容量以适应其大小。 该请求是非绑定的容器实现可以自由地进行优化使向量的容量大于其大小。 这可能会导致重新分配但对向量大小没有影响也不能改变其元素。 有效长度与容量操作 vector中的resize()与reserve()。其实他们的用法与特点也是与string类中的相同 当nsz时reserve并不会发生任何改变resize会删除有效字符到指定大小。当szncapcity时reserve并不会发生任何改变resize会补充有效字符(默认为0)到指定大小。当ncapacity时reserve会发生扩容resize会补充有效字符(默认为0)到指定大小。 void Test06()
{vectorint v1 { 1,2,3,4,5 };cout v1的有效长度为 v1.size() endl;cout v1的容量大小为 v1.capacity() endl;v1.reserve(10);cout reserve(10)后 endl;cout v1的有效长度为 v1.size() endl;cout v1的容量大小为 v1.capacity() endl;cout endl;v1.resize(8, 10);for (auto e : v1){cout e ;}cout endl;cout v1的有效长度为 v1.size() endl;cout v1的容量大小为 v1.capacity() endl;v1.resize(3);for (auto e : v1){cout e ;}cout v1的有效长度为 v1.size() endl;cout v1的容量大小为 v1.capacity() endl;}int main()
{Test06();return 0;
} 2.4. vector的访问操作 void Test07()
{vectorint v { 1,2,3,4,5 };for (int i 0; i v.size(); i){cout v.at(i) ;}cout endl;for (int i 0; i v.size(); i){cout v[i] ;}cout endl;cout front v.front() endl;cout back v.back() endl;
}int main()
{Test07();return 0;
} 2.5. vector的修改操作 首先先介绍最简单的四个函数push_back()pop_back()assign()swap()。
void Test7()
{vectorint v { 1,2,3,4,5,6 };cout back v.back() endl;//尾插v.push_back(7);//尾删cout back v.back() endl;v.pop_back();cout back v.back() endl;vectorint vv { 6,5,4,3,2,1 };//n个val赋值给原数组vv.assign(3, 2);for (int i 0; i vv.size(); i){cout vv[i] ;}cout endl;vv.swap(v);for (int i 0; i v.size(); i){cout v[i] ;}cout endl;for (int i 0; i vv.size(); i){cout vv[i] ;}
}介绍insert()与·earse()的用法这两个函数的用法就与string中的有所不同。首先是insert()函数 指定位置插入要注意的是这里不再像string一样用的size_t 的posvector虽然也可以用下标访问但是为了承接后面STL其他不支持下标访问的容器所以这边的pos用的是迭代器类型
void Test8()
{vectorint myvector(3, 100);vectorint::iterator it myvector.begin();//1.向指定位置插入一个元素it myvector.insert(it, 200);cout myvector contains:;for (it myvector.begin(); it myvector.end(); it)cout *it;cout endl;//2.向指定位置插入n个元素myvector.insert(it, 2, 300);cout myvector contains:;for (it myvector.begin(); it myvector.end(); it)cout *it;cout endl;//3.向指定位置插入一段迭代器区间it myvector.begin();vectorint anothervector(2, 400);cout myvector contains:;for (it myvector.begin(); it myvector.end(); it)cout *it;cout endl;it myvector.begin();myvector.insert(it 2, anothervector.begin(), anothervector.end());//4.向指定位置插入一段迭代器区间int myarray[] { 501,502,503 };myvector.insert(myvector.begin(), myarray, myarray 3);cout myvector contains:;for (it myvector.begin(); it myvector.end(); it)cout *it;cout endl;
}erase() 删除单个元素 当你需要删除向量中的某个特定元素时可以使用 erase 函数并传递一个指向该元素的迭代器。这将删除该元素并使后续元素向前移动一个位置。
删除多个元素 erase 函数还可以接受两个迭代器参数表示要删除的元素范围左闭右开区间。这允许你一次性删除多个连续的元素。
无论是哪种形式erase 的返回值都是一个迭代器指向被删除元素之后的位置即第一个未被删除的元素。如果删除的是容器中的最后一个元素或所有元素则返回 vector::end() 迭代器。
void Test9()
{//1.删除迭代器所指元素vectorint myvector;for (int i 1; i 10; i) myvector.push_back(i);vectorint::iterator it myvector.erase(myvector.begin() 5);it myvector.erase(it);//2.删除一段迭代器区间it myvector.erase(myvector.begin(), myvector.begin() 3);cout myvector contains:;for (int i 0; i myvector.size(); i)cout myvector[i];cout endl;
}虽然看起来vector的insert()和erase()与string的没有什么区别但是仔细观察就可以发现我们每次使用完迭代器之后都会更新这是为什么呢
主要还是因为我们每次插入数组都可能发生扩容而扩容分为就地扩容与异地扩容。如果发生的异地扩容这时的迭代器就不在指向原来的空间而就指向一块释放的内存我们一旦继续访问就会报错这种现象我们称为迭代器失效。为了避免出现这种情况所以我们在使用完迭代器之后需要更新。