前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++打怪 之 vector

C++打怪 之 vector

作者头像
开源519
发布2021-01-12 14:42:23
1.2K0
发布2021-01-12 14:42:23
举报
文章被收录于专栏:开源519开源519

1. 简介

❝Vector类 是在 java 中可以实现自动增长的对象数组,vector在C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。---百度百科 ❞

2. 场景实例

在C语言编程中,涉及到声明一个全局数组的时候,经常会遇到一种情况,数组的大小设定多少合适。一般情况下我们会设定一个比较大的值,例如1000甚至更大,主要就是怕在代码运行中,用到该数组时,若数组容量不够,出现越界的情况,从而导致宕机等较为严重的问题。但是设置过大,也会导致内存浪费,虽然不是什么大问题,但这种变量若定义过多,也会导致一笔不小的开销。在C语言中,可以通过动态数组来解决这一问题。但是在一些场景中,用起来较为复杂。


通过实际例子说明问题,声明一个结构体中,其中包含一个数组成员。

代码语言:javascript
复制
/* 因为无法确定name长度,不得不设定一个不可超越的较大值 */
#define NAME_LENGTH_MAX 100
struct STUDENT {
    char years;
    long id;
    char name[NAME_LENGTH_MAX];
};

在此实例中,我们可以发现,结构体STUDENT包含不确定长度的name成员,为了避免代码访问name数组越界,不得不声明一个不可超越的长度。这就会造成资源浪费的情况。一般情况下,可采用下面两种方法优化。


「优化1:C语言中采用动态数组优化」

代码语言:javascript
复制
struct STUDENT {
    char years;
    long id;
    char *name;
};

struct STUDENT std;

在用到std变量时,必须对std的name成员分配空间,否则会出现野指针问题,在运行时导致机器宕机。可通过malloc等函数对name进行分配空间。使用起来较为复杂。


「优化2:C++ vector」

代码语言:javascript
复制
struct STUDENT {
    char years;
    long id;
    vector<char> name;
};

用到std变量时,同样需要对name初始化,可采用vector提供的接口push_back赋初值即可。较优化1方案,使用起来方便一些。


3. 基本用法

C++ 中的vector实现实用的接口供开发者选择:

代码语言:javascript
复制
//头文件
#include <vector> 
using namespace std;

/* 构造方法 */
vector<类型>标识符
vector<类型>标识符(最大容量)
vector<类型>标识符(最大容量,初始所有值)
vector(const vector&) 复制vector
vector(begin,end) 复制数组begin到end之间的值到vector

/* E.g.几种较为常用的方法 */
vector<int> num; //int num[]
vector<char> num(5); //char num[];
vector<char> num(5, 1); //char num[] = {1,1,1,1,1};

int num[5]={1,2,3,4,5};
vector<int>num_copy(i+2,i+4);  //int num_copy[] ={3, 4, 5};

vector< vector<int> >num; //二维向量. 这里最外的<>要有空格。否则在比较旧的编译器下无法通过 int [][];

/* 常用接口 摘自 https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html*/
1.push_back 在数组的最后添加一个数据

2.pop_back 去掉数组的最后一个数据

3.at 得到编号位置的数据

4.begin 得到数组头的指针

5.end 得到数组的最后一个单元+1的指针

6.front 得到数组头的引用

7.back 得到数组的最后一个单元的引用

8.max_size 得到vector最大可以是多大

9.capacity 当前vector分配的大小

10.size 当前使用数据的大小

11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值

12.reserve 改变当前vecotr所分配空间的大小

13.erase 删除指针指向的数据项

14.clear 清空当前的vector

15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)

16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)

17.empty 判断vector是否为空

18.swap 与另一个vector交换数据

4. 实例

代码语言:javascript
复制
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string>
#include <vector>

using namespace std;

struct STUDENT {
    char years;
    long id;
    vector<int> name;
};

void show(vector<int> &vec)
{
    cout <<"Value: ";
    int num = 0;

    for (auto i = vec.begin(); i != vec.end(); i++) {
        cout << vec.at(num++) << " ";
    }
    cout << endl;
}

int main()
{
    struct STUDENT stud;
    vector<int> tmp(3, 5) ; //int tmp[] = {5, 5, 5}; 

    tmp.push_back(23);
    cout <<"---- 1st: "; 
    show(tmp);

    tmp.insert(tmp.begin(), 2, 10);
    cout <<"---- 2nd: "; 
    show(tmp);
    
    tmp.pop_back();
    cout <<"---- 3rd: ";
    show(tmp); 
    
    cout <<"---- 4th: " << tmp.capacity()<<endl;
    
    tmp.clear();
    cout <<"---- 5th: ";
    show(tmp);
    
    return 0;
}

「输出:」

代码语言:javascript
复制
---- 1st: Value: 5 5 5 23 
---- 2nd: Value: 10 10 5 5 5 23 
---- 3rd: Value: 10 10 5 5 5 
---- 4th: 6
---- 5th: Value:

5. 注意

在实际使用中,vector不当的用法可能会导致较为严重的问题:

  • 在使用vector变量时,必须对其初始化赋值才可以使用。若结构体含有vector成员,也必须先对此成员初始化,否则使用时可能会导致dump。
  • 在结构体有vector成员,不可用memset对此结构体进行清零,否则会导致内存泄漏。

按我的理解,C++中的「vector」 与 C中的 「指针 + malloc」 类似。只不过vector将动态数组的一系列操作都封装成标准库的接口。如果我们将「vector」理解成*「vector + malloc」 ,就能够分析出以上问题的原因:

  • 第一个问题理解。vector是一个指针,如果没有初始化赋值,就是一个野指针。那么在使用没有初始化的vector,就如同在使用野指针,会导致宕机。
  • 第二个问题理解。在初始化后,vector就是一个指针指向了一篇连续的内存,如果使用memset对含有vector成员的结构体清零,那么就会改变vector的指向对象,那么之前的内存还没有释放就被丢失掉了,导致内存泄漏。

6. 总结

c++中vector解决了C语言中声明数组时无需确定范围,其实现方式类似于C语言中的动态数组。不过较C++实现了vector的各种接口,其接口功能看起来也比较符合动态数组的功能。C++实用的功能接口还有很多,后续开发遇到会及时总结出来。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源519 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 简介
  • 2. 场景实例
  • 3. 基本用法
  • 4. 实例
  • 5. 注意
  • 6. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档