STL容器\vector学习随笔

vector详介成员函数[官方版]

vector简介成员函数[江湖版]
vector详介成员函数[江湖版]


iterator详介使用操作[官方版]


还未了解过vector的,请先通过上面的文件,做一个大概的了解


读前概要:

头文件:#include 
  • 位置获取
    • begin()
    • end()
    • rbegin()
    • rend()
    • cbegin()
    • cend()
    • crbegin()
    • crend()
  • 数据修改
    • assign()
    • push_back()
    • pop_back()
    • insert()
    • erase()
    • swap()
    • clear()
    • emplace()
    • emplace_back()
  • 空间大小
    • size()
    • max_size()
    • resize()
    • capacity()
    • empty
    • reserve
    • shrink_to_fit
  • 数据获取
    • at()
    • operator[]
    • front()
    • back()
    • data()

心得分享

下面是我对自己在学习中的心得分享,不做教学使用

begin与end的位置关系

/*
    此函数证明了
    begin()与end()
    位置关系
                        */

//#include "stdafx.h"
#include 
#include 
#include 


using namespace std;


int main()
{
    vector<int> ivec(4096, 110);
    vector<int> iveccp(ivec.begin(), ivec.end());
    vector<int>::iterator iter = ivec.end();
    assert(ivec == iveccp);

    assert(ivec.begin() + ivec.size() == ivec.end());
    assert(ivec.end() - ivec.size() == ivec.begin());
    assert(ivec.begin() - ivec.end() == -vector<string>::difference_type(ivec.size()));

    // * end()他返回的地方不含任何元素,
    // * 只是单纯的表示元素的尾部,
    // * 就好比瓶口没有水,有的是盖子,盖子不是水。

    return 0;
}

STL/for循环心得:

迭代器(暂且可以把迭代器抽象的理解成指向vector类型的指针)
    iterator begin:
    begin 返回的是迭代器,他指向vector的首元素.

    iterator end:
    end 返回的也是迭代器,他指向vector的尾端(不是指向尾元素).一般用于测定是否已经读完数据.

关于for循环的效率问题文章

【C++11的for循环,以及范围Range类的实现】
【C++11新特性的for循环个人测试感悟】
【std::vector的几种遍历方式比较】

/*
    begin()与end()的遍历应用
    用 auto 与 ':' 代替冗余的迭代器
                                    */
//#include "stdafx.h"
#include 
#include 

using namespace std;

int main()
{
    // 初步了解.
    std::vector<int> vec(2);
    std::vector<int>::iterator pvec = vec.begin();
    std::cout << "vec第一个元素: "<< *pvec << std::endl;   // 打印 0 

    pvec = vec.end();
    //std::cout << *pvec << std::endl;    //error: end()返回的并不是一个有效的值.


    // 循环遍历容器中的值.
    std::vector<int> iVec(10); 
    /* 
       声明迭代器iterVec并指向iVec的首元素; 
       如果迭代器iterVec已经指向end点则跳出循环;
       每次循环增加一个(int)步长  
    */
    for(std::vector<int>::iterator iterVec = iVec.begin(); iterVec != iVec.end(); ++iterVec)
        std::cout << *iterVec << ' ';
    std::cout << std::endl;

///////////////////////////////////////////////////////////////////////////
    // * 以后就用如下方式,对数组容器等进行逐一访问
    // * 该函数等价于上面的函数,这是C++11的新特性,auto的类型判断,和 ':' 的遍历功能.

    for( auto x : iVec )
        std::cout << x << ' ';
    std::cout << std::endl;

    // * 用C++11的新特性还有另一个优点,就是在判定条件语句中
    // * iterVec != iVec.end() 每次都是调用 end()
    // * 进入end()内部实现,你会发现每次返回的值都是一样的
    // * 使用新特性后,自然也就减少了,赋值拷贝,等一系列的操作
    // * 提高了程序的效率,简洁了代码 ———— 俗称优化
///////////////////////////////////////////////////////////////////////////

    return 0;
}

insert与迭代器:

iterator insert(pos,elem)
    在pos位置插入一个elem拷贝,传回新数据位置。
iterator insert(pos,n,elem)
    在pos位置插入n个elem数据。传回新数据位置。
iterator insert(pos,beg,end)
    在pos位置插入在[beg,end)区间的数据。传回新数据位置。
/*
    iterator迭代器的谨慎使用
    在很多操作中都会成野指针
    野指针会带来程序的一级错误
                            */
//#include "stdafx.h"
#include 
#include 

using namespace std;

int main()
{
    std::vector<int> iVec(3, 100);
    std::vector<int>::iterator it;

    it = iVec.begin();

    iVec.insert(it, 200);
    //std::cout << *it << std::endl;        // * error: 因为iVec的地址已经变了.
    // * 此时 it 可能已经是野指针了,因为插入了一个新数据,地址空间变大,
    // * 动态数组 iVec 为了增大空间,不得不另寻一处更大的空间来存放数据
    // * 之所以说 it 的指针 只是可能野,而不是一定野的原因是.
    // * 如果其后方位置足够充裕,可以向后申请空间的话,他就不会 "搬家"
    std::cout << "iVec 包含:";
    for (auto x : iVec)
        std::cout << ' ' << x;
    std::cout << '\n';;


    // * 让动态数组 iVec "不搬家"
    std::vector<int> iVecStay(10);
    std::cout << "当前 iVecStay 元素个数:" << iVecStay.size() << std::endl
            << "当前 iVecStay 空间大小:" << iVecStay.capacity() << std::endl;

    vector<int>::iterator iter = iVecStay.begin();
    iVecStay.reserve(4096);         // iter已经指向了无效数据成为野指针 
    // * 不出意外的话,iVecStay 已经"搬家", 而且搬到"比较大的家"


    iter = iVecStay.begin();
    iVecStay.insert(iter, 200);
    std::cout << *iter << std::endl;
    // * 讲道理的话,这里应该是可以显示出正常的数据的,并且这个数据依然是 iVecStay.begin() 的值
    // * 简而言之, 正如我上面所说的那样,现在 iVecStay 的房子够大,来这么几个小妾并不至于让这个财主搬家.

    return 0;
}

数组声明与at

/*
    网上没怎么查到讲数组的
    故自己在这里梳理一下
    以及提醒自己对于动态数组 
    at()的重要性
                            */
//#include "stdafx.h"
#include 
#include 
 int main()
 {
    std::vector<int>::iterator iters; 
    std::vector<int> ivec(5, 1);

    for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
        *iter = 3;

    ivec.push_back(5);  // 当前容器内数据是 3 3 3 3 3 5

    std::vector<vector<int> > iarr(ivec.begin(), ivec.end());
    // * ivec.size() 成了 iarr 的二维项
    // * ivec中的每个元素成为了 iarr 的一维项
    // * 故 iarr可以写成 iarr[6][x]  x 等于 ivec中的对应元素值

    // * 说到数组,不得不提at(),at防止数组越界给出了至关重要的地位.
    // * 故提倡使用at(),在无意间数组越界时,会抛出异常,能够防止程序崩溃,提升程序健壮性.

///////////////////////////////////////////////////////////////////////////
    try{
        ivec.at(4096);
    }
    catch(...){
        std::cout << "value invalid" << std::endl;
        std::cout << "增加了程序的健壮性,不至崩溃." << std::endl;
        system("pause");
    }
///////////////////////////////////////////////////////////////////////////

    return 0;
 }

注:以上均为个人学习随笔,其内容甚是肤浅,如有错误,请务必指正!

你可能感兴趣的:(STL容器\vector学习随笔)