【校招面试 之 C/C++】第20题 C++ STL(二)之Vector

1、vector的动态增长

  当添加元素时,如果vector空间大小不足,则会以原大小的两倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。vector的空间动态增加大小,并不是在原空间之后的相邻地址增加新空间,因为vector的空间是线性连续分配的,不能保证原空间之后有可供配置的空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就会失效。

vector的size(),capacity(),reserve(),resize()函数:

vector对象的内存布局如下图所示:

start迭代器指向已用空间的首元素,finish指向已用空间的尾元素的下一个位置,end_of_storage指向可用空间的末尾。

size()函数返回的是已用空间大小,capacity()返回的是总空间大小,capacity()-size()则是剩余的可用空间大小。当size()和capacity()相等,说明vector目前的空间已被用完,如果再添加新元素,则会引起vector空间的动态增长。

由于动态增长会引起重新分配内存空间、拷贝原空间、释放原空间,这些过程会降低程序效率。因此,可以使用reserve(n)预先分配一块较大的指定大小的内存空间,这样当指定大小的内存空间未使用完时,是不会重新分配内存空间的,这样便提升了效率。只有当n>capacity()时,调用reserve(n)才会改变vector容量。

resize()成员函数只改变元素的数目,不改变vector的容量。

程序说明:

分配了两个容器a,b。其中每次往a中添加1个元素,共添加10次。使用reserve()预先为b分配一块10个元素大小的空间,之后才每次往b中添加1个元素,共添加10次。当b空间满后,再往其中添加1个元素。之后使用reserve()为b分配一块15(比原空间小)个元素大小的空间。再使用resize()将b的元素个数改变为5个。

观察上述过程中size()和capacity()大小的变化。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> a;
    cout << "a.size(): " << a.size() << "       a.capacity(): " << a.capacity() << endl;
    for (int i = 0; i < 10; i++)
    {
        a.push_back(i);
        cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;
    }
    cout << endl;
    vector<int> b;
    b.reserve(10);
    for (int i = 0; i < 10; i++)
    {
        b.push_back(i);
        cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;
    }
    b.push_back(11);
    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;
    cout << endl;
    b.reserve(15);
    cout << "after b.reserve(15):" << endl;
    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;
    b.resize(5);
    cout << "after b.resize(5):" << endl;
    cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;
    return 0;
}
输出:a.size(): 0     a.capacity(): 0
a.size(): 1     a.capacity(): 1
a.size(): 2     a.capacity(): 2
a.size(): 3     a.capacity(): 4
a.size(): 4     a.capacity(): 4
a.size(): 5     a.capacity(): 8
a.size(): 6     a.capacity(): 8
a.size(): 7     a.capacity(): 8
a.size(): 8     a.capacity(): 8
a.size(): 9     a.capacity(): 16
a.size(): 10    a.capacity(): 16
b.size(): 1     b.capacity(): 10
b.size(): 2     b.capacity(): 10
b.size(): 3     b.capacity(): 10
b.size(): 4     b.capacity(): 10
b.size(): 5     b.capacity(): 10
b.size(): 6     b.capacity(): 10
b.size(): 7     b.capacity(): 10
b.size(): 8     b.capacity(): 10
b.size(): 9     b.capacity(): 10
b.size(): 10    b.capacity(): 10
b.size(): 11    b.capacity(): 20
after b.reserve(15):
b.size(): 11    b.capacity(): 20
after b.resize(5):
b.size(): 5     b.capacity(): 20

现象:a重新分配空间共5次,每次都为之前空间的2倍。b在未超出reserve()预分配的空间时没有重新分配。

结论:

1. 空的vector对象,size()和capacity()都为0

2. 当空间大小不足时,新分配的空间大小为原空间大小的2倍。

3. 使用reserve()预先分配一块内存后,在空间未满的情况下,不会引起重新分配,从而提升了效率。

4. 当reserve()分配的空间比原空间小时,是不会引起重新分配的。

5. resize()函数只改变容器的元素数目,未改变容器大小(capacity())。

2、vector的用法

(1)头文件

#include<vector>

(2)声明以及初始化

vector<int> vec;        //声明一个int型向量
vector<int> vec(5);     //声明一个初始大小为5的int向量
vector<int> vec(10, 1); //声明一个初始大小为10且值都是1的向量
vector<int> vec(tmp);   //声明并用tmp向量初始化vec向量
vector<int> tmp(vec.begin(), vec.begin() + 3);  //用向量vec的第0个到第2个值初始化tmp
int arr[5] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr + 5);      //将arr数组的元素用于初始化vec向量
//说明:当然不包括arr[4]元素,末尾指针都是指结束元素的下一个元素,
//这个主要是为了和vec.end()指针统一。
vector<int> vec(&arr[1], &arr[4]); //将arr[1]~arr[4]范围内的元素作为vec的初始值

(3)基本操作

1??容量

  • 向量大小: vec.size();
  • 向量最大容量: vec.max_size();
  • 更改向量大小: vec.resize();
  • 向量真实大小: vec.capacity();
  • 向量判空: vec.empty();
  • 减少向量大小到满足元素所占存储空间的大小: vec.shrink_to_fit(); //shrink_to_fit

2??修改

  • 多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
  • 末尾添加元素: vec.push_back();
  • 末尾删除元素: vec.pop_back();
  • 任意位置插入元素: vec.insert();
  • 任意位置删除元素: vec.erase();
  • 交换两个向量的元素: vec.swap();
  • 清空向量元素: vec.clear();

3??迭代器

  • 开始指针:vec.begin();
  • 末尾指针:vec.end(); //指向最后一个元素的下一个位置
  • 指向常量的开始指针: vec.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
  • 指向常量的末尾指针: vec.cend();

4??元素的访问

  • 下标访问: vec[1]; //并不会检查是否越界

    • at方法访问: vec.at(1);   //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
  • 访问第一个元素: vec.front();
  • 访问最后一个元素: vec.back();
  • 返回一个指针: int* p = vec.data(); //可行的原因在于vector在内存中就是一个连续存储的数组,所以可以返回一个指针指向这个数组。这是是C++11的特性

5??算法

遍历

vector<int>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
    cout << *it << endl;
//或者
for (size_t i = 0; i < vec.size(); i++) {
    cout << vec.at(i) << endl;
}

原文地址:https://www.cnblogs.com/xuelisheng/p/9347544.html

时间: 2024-10-03 05:08:46

【校招面试 之 C/C++】第20题 C++ STL(二)之Vector的相关文章

【校招面试 之 C++】第1题 为什么优先使用构造函数的初始化列表

1.首先看一个例子: #include<iostream> using namespace std; class Test1 { public: Test1() // 无参构造函数 { cout << "Construct Test1" << endl ; } Test1(const Test1& t1) // 拷贝构造函数 { cout << "Copy constructor for Test1" <

【校招面试 之 C++】第4题 拷贝构造函数被调用的3个时机

1.被调用的3个时机: (1)直接初始化或拷贝初始化: (2)将一个对象作为一个实参传递,形参采用非指针或非引用的对象进行接收时: (3)函数的返回值是一个非指针或者非对象被接收时. 2.举例说明: #include <iostream> using namespace std; class Test{ private: int a; int b; static int count; public: Test(int i, int j): a(i), b(j){} void print();

【校招面试 之 C++】第13题 C++ 指针和引用的区别

1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址. 而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单元. (2)可以有const指

2018百度校招面试总结

2018百度校招面试总结 目前走流程到二面, 写一波面经希望能够收到三面通知, 上天请赐予我运气和力量吧: 校招走流程的两个面试官都很nice, 比较随和, 面试体验非常好; 百度一面 在酒店一楼等面试官通知, 叫到名字就坐电梯去对应房间号面试; 交完简历, 面试官会安静的浏览简历(这时候比较尴尬, 只有静静的等), 然后面试官会让你简单的自我介绍; 面试官后面会对感兴趣的项目进行细节询问, 大致包括: 解决一个什么问题; 项目的背景; 数据处理流程; 大概的项目框架; 自己对整个项目的理解;

剑指Offer名企面试官精讲典型编程题pdf

下载地址:网盘下载 <剑指Offer:名企面试官精讲典型编程题(第2版)>剖析了80个典型的编程面试题,系统整理基础知识.代码质量.解题思路.优化效率和综合能力这5个面试要点.<剑指Offer:名企面试官精讲典型编程题(第2版)>共分7章,主要包括面试的流程,讨论面试每一环节需要注意的问题:面试需要的基础知识,从编程语言.数据结构及算法三方面总结程序员面试知识点:高质量的代码,讨论影响代码质量的3个要素(规范性.完整性和鲁棒性),强调高质量代码除完成基本功能外,还能考虑特殊情况并对

leetcode第20题--Valid Parentheses

Problem: Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "

OCJP(1Z0-851) 模拟题分析(二)

Exam : 1Z0-851 Java Standard Edition 6 Programmer Certified Professional Exam 以下分析全都是我自己分析或者参考网上的,定有疏漏,还请大家对我的分析提出质疑. QUESTION 31 Given:1. interface A { public void aMethod(); }2. interface B { public void bMethod(); }3. interface C extends A,B { pub

编程题:用二维字符串数组实现。从键盘输入三个学生姓名,并输出。

#include<stdio.h> #include<string.h> void main() { char name[3][30]; int i; for(i=0;i<3;i++) gets(name[i]);  /*name[i]是一个一维字符数组*/ for(i=0;i<3;i++) printf("%s\n",name[i]); } 编程题:用二维字符串数组实现.从键盘输入三个学生姓名,并输出.,布布扣,bubuko.com

编程题:指向二维数组元素的指针变量。功能:已知二维数组a[2][3],输入输出全部元素。

#include<stdio.h> void main() { int a[2][3],i,j; int *p; /*用坐标法输入二维数组元素*/ for(i=0;i<2;i++) for(j=0;j<3;j++) scanf("%d",&a[i][j]); /*用指针法输出二维数组元素*/ p=a[0];         /*等价于p&a[0][0];*/ for(;p<a[0]+6;p++)   printf("%4d&quo