C++标准库类型vector

头文件

#include <vector>
using std::vector;

定义和初始化

vector常用的初始化方法为:

// 默认初始化: v不含任何元素, 但是只能添加类型T的元素
vector<T> v1;

// 拷贝初始化: v2中包含v1所有元素的副本
vector<T> v2 = v1;
vector<T> v2(v1);

// 初始化指定数量元素
vector<T> v1(n, val);  // 包含n个值为val的元素
vector<T> v1(n);       // 包含n个执行了值初始化(内置类型零初始化, 类类型默认构造函数初始化)的元素

// 列表初始化
vector<T> v1 {a, b, c};
vector<T> v1 = {a, b, c};

注意vector的圆括号与花括号初始化是不同的:圆括号是通过调用vector的构造函数进行初始化的,如果使用了花括号那么初始化过程会尽可能会把花括号内的值当做元素初始值的列表来处理。如果初始化时使用了花括号但是提供的值又无法用来列表初始化,那么就考虑用这些值来调用vector的构造函数了。

#include <string>
#include <vector>

int main() {
    std::vector<std::string> v1{"tomo", "cat", "tomocat"};  // 列表初始化: 包含3个string元素的vector
    // std::vector<std::string> v2("a", "b", "c");          // 错误: 找不到合适的构造函数

    std::vector<std::string> v3(10, "tomocat");             // 10个string元素的vector, 每个string初始化为"tomocat"
    std::vector<std::string> v4{10, "tomocat"};             // 10个string元素的vector, 每个string初始化为"tomocat"

    std::vector<int> v5(10);     // 10个int元素, 每个都初始化为0
    std::vector<int> v6{10};     // 1个int元素, 该元素的值时10
    std::vector<int> v7(10, 1);  // 10个int元素, 每个都初始化为1
    std::vector<int> v8{10, 1};  // 2个int元素, 值分别是10和1
}

添加元素

push_back负责把一个值加到vector对象的尾端:

// 初始化一个空vector对象, 依次将0~99
vector<int> vi;
for (int i = 0; i != 100; ++i) {
    vi.push_back(i);
}

vector其他操作

v.empty()     // v中不含有任何元素时返回true
v.size()      // 返回v中元素数量
v[n]          // 返回v中第n个位置上元素的引用
v1 == v2
v1 != v2      // v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值相同
<, <=, >, >=  // 以字典顺序进行比较

vector常见错误

1. 范围for循环内给vector对象添加/删除元素

在范围for循环中预存了end()的值,一旦在序列中添加(删除)元素,那么end()函数的值就可能变得无效了。

2. 不能用下标添加元素,也不能访问不存在的元素

Tips:vector与string等对象的下标运算符可用于访问已存在的元素,但不能用于添加元素。确保下标有效的一种有效手段就是尽可能地使用范围for语句。

vector<int> vi;
vi[0] = 10;      // 严重错误: 访问了不存在的元素

vector对象增长

1. vector对象能高效增长

Tips:开始的时候创建空的vector对象,在运行时再动态添加元素,这一做法与C语言以及其他大多数语言中内置数组类型的用法不同。特别是如果习惯了C或者Java,可能预计在创建vector对象时顺便指定其容量是最好的,然而事实上恰恰相反。

C++标准要求vector能在运行时高效快速地添加元素,既然vector对象能高效地增长,那么定义vector对象的时候设定其大小也就没什么必要了,事实上如果这么做性能可能更差。只有一种例外情况,就是所有元素的值都一样。一旦元素的值有所不同,更有效的方法是先定义一个空的vector对象,再在运行时向其中添加具体值。

2. vector对象增长机制

Tips:这种分配策略比每次添加新元素时都重新分配容器内存空间的策略要高效得多。对比其他容器而言,虽然vector在每次重新分配内存空间时都要移动所有元素,但其扩张操作通常比list和deque还要快。

为了支持快速随机访问,vector将元素连续存储到一块内存区域。由于元素必须连续存储,每次添加新元素时容器必须分配新的内容空间来保存已有元素和新的元素,将已有元素从旧位置移动到新空间中,添加完新元素后释放旧存储空间。如果我们每次添加一次新元素vector就执行一次这样的内存分配和释放操作,那么性能会慢到不可接受。

为了避免这种操作,标准库采用了可以减少容器空间重新分配次数的策略,当不得不获取新的内存空间时,vector和string的实现通常会分配比新的空间需求更大的内存空间,容器预留这些空间作为备用来存储可能新增的元素。这样就不需要每次添加新元素都重新分配容器的内存空间了。

3. size和capacity

vector中的size指它已经保存的元素数量,capacity指的是在不分配新的内存空间条件下可以容纳的元素数量。

vector和string类型提供了一些成员函数让我们可以参与它的内存分配:

c.shrink_to_fit();  // 将capacity()减少到与size()相同大小
c.capacity();       // 不重新分配内存的情况下c可以容纳的元素数量
c.reserve(n);       // 分配至少能容纳n个元素的内存空间

Reference

[1] C++ Primer

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容