标准库类型vector

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fsdgsddaer/article/details/79945678

做毕设,里面需要实现一个有关动态规划的算法,用到vector,map,set 这些容器(container) 。

vector 挺简单的,写这篇关于vector 的博客,有两个目的:

  1. 了解C++11中的几个新特性。(C++17都出来了,C++特性一点都不新呀...,姑且称为C++11新特性)
  2. 简单的知识更要熟练掌握啊,骚年。

我们平时写程序,都直接用C++11,没有什么问题!

可是我的毕设项目,不能用C++11,一用就出错,貌似是与项目中用到的 boost/shared_ptr 冲突了。

以下背景为粉红的都是C++11中才有的。

1. 示例程序1

下面介绍下vector 初始化,看程序1:

//程序1 test.cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main(){
    //默认初始化
    vector<string> vs1;
    vs1.push_back("set");
    vs1.push_back("deadlines");
    vs1.push_back("for");
    vs1.push_back("everything");
    for(int i=0;i<vs1.size();++i){
        cout<<vs1[i]<<' ';
    }   
    cout<<endl;
    
    //拷贝初始化vs2,把vs1里的元素全部赋给vs2
    vector<string> vs2(vs1);    //等同于,vector<string> vs2=vs1;
    for(int i=0;i<vs2.size();++i){
        cout<<vs2[i]<<' ';
    }   
    cout<<endl;

    vector<string> vs3;
    //把vs1里的元素全部赋给vs3
    vs3=vs1;
    for(string i:vs3){
        cout<<i<<' ';
    }   
    cout<<endl;
    return 0;
}

上面的程序,体现了两种初始化vector 的方式。

  • 默认初始化,vector不含任何元素
  • 拷贝初始化,很多类都有拷贝构造函数,用于拷贝初始化

此外,还有两种初始化方式:

  • vector<string> svec(10, "hello")   // sevc对象中有10个string类型元素---"hello"
  • vector<string> svec={"are", "you", "OK"}   // 列表初始化,C++11新特性

注:vector对象能高效增长,建议用默认初始化 [ 1 ] ,然后动态push_back添加元素。

事实上,定义vector对象时设定其元素,可能性能更差!

C++11新特性:范围for (range for)

程序1这样编译:

g++ -o test test.cpp

不会报错,会报一个警告。可是运行时会出错,原因在于,range for是C++11特性,必须这样编译

g++ -std=C++11 -o test test.cpp
既然都用范围for了,那么可以更方便一点,使用auto类型说明符

关于auto:

  • 能自动推导出表达式类型
  • auto一般会忽略顶层const,保留底层const,和decltype不同
  • auto最常用的就是 推导类型auto i ; 和 推导引用类型auto &i ; 也常用与推导迭代器类型

2. vector 部分操作[1]

  1.  v.empty()   如果v 不含任何元素,返回true ,否则false
  2.  v.size()      返回v 中元素的个数
  3.  v.push_back(t)   在v 的尾端添加元素 t 
  4. v[ n ]    返回第n 个位置上元素的引用,n从0开始,注意:不能用 v[n] 添加元素
  5.  v1=v2  用v2 中的元素 拷贝替换 v1中的元素,即,v1被v2覆盖了
  6. v1 = { a, b, c...}  用列表中的元素拷贝覆盖v1 中的元素,C++11特性
  7. v1==v2   v1和v2元素数量相同且对应位置元素相等
  8. v1 != v2
  9.  <, <=, >, >=   按字典顺序比较

3.迭代器(iterator)介绍

string 和 容器(container) 都可以通过 自身拥有的 begin()end() 成员获取迭代器。

vector<string> vs;

auto b=vs.begin();
auto e=vs.end();

上面的代码里,be 的类型一样,都是vector<string>::iterator   。

其中b 指向vs 的第一个元素;e指向vs 的尾元素的下一个位置(一个不存在元素的位置)。

end成员返回的迭代器通常称为尾后迭代器(off-the-end iterator)

事实上,begin 和 end 返回的具体类型由对象是否为常量决定:

vector<int> vi;
const vector<int> cvi;

auto it1=vi.begin();
auto it2=cvi.begin();

auto it3=vi.cbegin();

上面代码中,it1 的类型是vector<int>::iterator  ,it2 和 it3 的类型相同vector<int>::const_iterator   。

cbegin 和 cend 是C++11特性


迭代器的运算符:

  1.  *iter  返回迭代器iter 所指元素的引用
  2.  iter->mem  解引用iter 并获取该元素(对象)的mem 成员,等价与 (*iter).mem
  3.  ++iter
  4.  --iter
  5.  iter1 == iter2  判断两个迭代器是否相等,相等返回true
  6.  iter1 != iter2

注:如果一个vector 没有元素,那么begin 和 end 成员返回的结果是相等的。

迭代器运算:

  1.  iter+n     迭代器加上一个整数值后,迭代器指示的位置朝着end 方向移动n 。结果指示容器内的一个元素,或指示容器尾元素的下一个位置
  2.  iter-n
  3.  iter+=n
  4.  iter-=n
  5.  iter1-iter2   结果是两个迭代器之间的距离
  6.  >, >=, <, <=  越靠近end ,迭代器的值就越大    
//计算得到最接近vi 中间元素的一个迭代器
auto mid = vi.begin() + vi.size()/2 ;



References: 

[1] C++ Primer 中文版 (第5版)



阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页