C++语言STL标准容器类Vector的基本使用

在C语言程序开发中,若是遇到了不能确定长度的数据类型结构,链表常常是一个不错的选择,但是C语言并未提供原生的链表结构,程序员不得不自己设计一套链表管理机制。虽说开源社区也提供了不少好用的通用设计,但毕竟不是C语言原生的语法,统一性有所欠缺。C++大概是察觉到了这一点,提供了一些不错的模板类,例如 STL 中的 Vector 就是一个很好用的模板类。

怎样定义 Vector?

C++语言中的 Vector 是一个动态的序列容器,随着元素的插入删除,它的 size 会自动的改变。Vector 在内存分布上有些类似于数组,其内部存储的元素是连续存储的,因此可以像数组那样通过下标访问各个元素。

Vector 属于标准命名空间 std,使用它需要包含头文件<vector>

#include <vector>

然后便可定义 vector 对象了,因为 vector 是一个模板类,因此在定义对象时,应指明数据结构,例如:

std::vector<int> myvec;

上面这行C++语言代码便定义了一个 int 类型的 vector 对象 myvec,因此 myvec 可以存储若干 int 类型的数据。

初始化 Vector

在C++11标准之后,初始化 vector 可以在定义时直接执行,例如下面这段C++语言代码:

#include <vector>

int main()
{
    std::vector<int> myvec = {1, 1, 2, 3, 5};
    return 0;
}

在上面这段代码中,我们定义了一个 vector 对象 myvec,并在其中存储了 5 个 int 型的元素,按照前面讨论的,vector 容器内部的元素在内存上是连续的,因此此时 myvec 的内存模型大致如下,请看:

myvec 的内存模型

此时的 myvec 看起来和数组没什么两样,但是数组的长度一旦确定下来,就不能再改变了,而 vector 却可以根据实际需要动态的改变长度,此时 vector 又有些像“链表”。。

Vector 的迭代器

前面几节讨论其他几种STL容器时,都提到了相应的迭代器,vector 容器类也不例外,它也有这些通用的设计,通过迭代器,我们能够轻易的访问容器中的各个元素。

  • begin:返回指向vector中第一个元素的迭代器指针。
  • end:返回最后一个元素接下来位置(也即结束位置)的迭代器指针。
  • rbegin 和 rend:类似于 begin 和 end,只不过是反向(reverse)的
  • cbegin 和 cend:类似于 begin 和 end,只不过返回的迭代器指针是只读的(const)。
  • crbegin 和 crend:前缀 cr 分别是 reverse 和 const。

下面是一段使用这几个迭代器的C++语言代码示例,请看:

#include <iostream>
#include <vector>
using namespace std;
int main()
{ 
    vector<int> v1;

    for (int i = 1; i <= 5; i++)
       v1.push_back(i+1);

       cout << "Output of Vector with begin and end: ";
    for (auto i = v1.begin(); i != v1.end(); ++i)
       cout << *i << " ";

       cout << "\nOutput of Vector with rbegin and rend: ";
    for (auto itr = v1.rbegin(); itr != v1.rend(); ++itr)
       cout << *itr << " ";

       cout << "\nOutput Vector of with cbegin and cend: ";
    for (auto itc = v1.cbegin(); itc != v1.cend(); ++itc)
       cout << *itc << " ";

       cout << "\nOutput Vector of with crbegin and crend : ";
    for (auto icr = v1.crbegin(); icr != v1.crend(); ++icr)
       cout << *icr << " ";

    return 0;
}

编译这段C++语言代码时记得指定-std=c++11选项,执行编译后的程序,得到如下输出:

# g++ t2.cpp -std=c++11
# ./a.out 
Output of Vector with begin and end: 2 3 4 5 6 
Output of Vector with rbegin and rend: 6 5 4 3 2 
Output Vector of with cbegin and cend: 2 3 4 5 6 
Output Vector of with crbegin and crend : 6 5 4 3 2

上述C++语言代码定义了一个 vector 对象并使用 push_back() 函数插入了若干元素,接着,我们使用了每一个迭代器函数遍历了 vector 容器中的各个元素,结合前文的解释,输出应该很好理解。

vector 元素排序

vector 容器中的元素顺序和它们被插入的顺序是一致的,不过得到一个排序后的元素序列是常有的需求,此时可使用 sort() 函数,例如下面这段C++语言代码示例:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
 {
   vector<int> myvec = {10,50,30,20,60,40};

   cout<<"Original Vector"<<endl;
   for(auto i=myvec.begin();i<myvec.end();++i)
      {
        cout<<*i<<" ";
      }
   cout<<endl;

   sort(myvec.begin(),myvec.end());

   cout<<"Sorted Vector"<<endl;
   for(auto i=myvec.begin();i<myvec.end();++i)
      {
        cout<<*i<<" ";
      }
   cout<<endl;

   return 0;
}

编译并执行之,得到如下输出:

# g++ t3.cpp -std=c++11
# ./a.out 
Original Vector
10 50 30 20 60 40 
Sorted Vector
10 20 30 40 50 60

sort() 函数本身是一个位于 std 命名空间的模板函数,它的部分代码如下图所示:

sort() 函数的部分代码

可见,sort() 函数接收两个迭代器指针,它会将两个迭代器之间的元素排序。并且通过注释能够看出,sort() 函数排序的基本判断是 *(i+1)<*i,程序员应自己把握这一点。

vector 的容量

成员函数 size() 可以返回当前 vector 容器内部存储的元素个数,按照前文讨论的,vector 容器类对象可以像数组那样访问元素,二者结合使用也是非常顺手的操作,例如下面这段C++语言代码示例:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> myvec = {1, 1, 2, 3, 5, 8};
    cout << "Vector Size : " << myvec.size() << endl;

    for (size_t i=0; i<myvec.size(); i++)
        cout << myvec[i] << " ";
    cout << endl;

    return 0;
}

编译这段代码并执行,得到如下输出:

# g++ t4.cpp -std=c++11
# ./a.out 
Vector Size : 6
1 1 2 3 5 8

这么看来,将元素插入到 vector 容器的随机位置也是极其方便的,只需要指定下标就可以了:

myvec[random] = val;

但是这么做要确保 random 的值不超过 myvec.size(),否则就会导致错误。幸好C++语言中的 vector 提供了 resize() 函数,它可以将 vector 的容量也即 myvec.size() 改变到期望大小,下面是一段C++语言代码示例:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> myvec;
    myvec.resize(4);
    cout << "\nVector Size after resize: " << myvec.size();
    for (size_t i=0; i<myvec.size(); i++)
        myvec[i] = i*3;

    cout << "\nVector elements are: ";
    for (auto it = myvec.begin(); it != myvec.end(); it++)
        cout << *it << " ";
    cout << endl;

    return 0;
}

编译并执行这段代码,得到如下输出:

# g++ t5.cpp -std=c++11
# ./a.out 

Vector Size after resize: 4
Vector elements are: 0 3 6 9

删除元素

类似于其他 STL 容器类,vector 也提供了 erase() 函数用于删除指定的元素。erase() 函数接收一个迭代器指针参数,用于指定被删除元素的位置,因此期望删除第 i 个元素的C++语言代码可以是下面这样的:

myvec.erase(myvec.begin() +i);

下面是一段完整的C++语言代码示例,请看:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    // Initialize vector
    vector<int> myvec = {1,1,2,3,5};
    cout << "\nVector elements:";
    for (int i = 0; i < myvec.size(); i++)
        cout << myvec[i] << " ";

    // remove the first element
    myvec.erase(myvec.begin());
    cout<<"\nVector size after erase: "<<myvec.size();

    cout << "\nVector after erase operation: ";
    for (int i = 0; i < myvec.size(); i++)
        cout<<myvec[i]<<" " ;
    cout << endl;

    return 0;
}

编译并执行这段C++语言代码,可以得到如下输出,请看:

# g++ t6.cpp -std=c++11
# ./a.out 

Vector elements:1 1 2 3 5 
Vector size after erase: 4
Vector after erase operation: 1 2 3 5 

另外一个需要说明的 vector 容器类的成员是 clear() 函数,它可以将容器内部的所有元素都删除:

myvec.clear();

因此要慎重使用 clear() 函数。

插入元素

C++语言中的 vector 容器类还提供了 insert() 函数用于插入元素到指定位置,下面是一段C++语言代码示例,请看:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    // Assign vector
    vector<int> myvec = {2,3,4};

    cout << "\nInitial vector: ";
    for (int i = 0; i < myvec.size(); i++)
        cout << myvec[i] << " ";

    // inserts 20 at the beginning, 30 after that
    myvec.insert(myvec.begin(), 20);
    myvec.insert(myvec.begin()+1,30);
    cout << "\nNew vector after insert: ";
    for (int i = 0; i < myvec.size(); i++)
        cout << myvec[i] << " ";
    cout << endl;

    return 0;
}

编译并执行这段C++语言代码,可以得到如下输出,请看:

# g++ t7.cpp -std=c++11
# ./a.out 

Initial vector: 2 3 4 
New vector after insert: 20 30 2 3 4

程序一开始定义了 vector 对象 myvec,并且给了 3 个初值,稍后使用 insert() 函数将 20 和 30 两个元素插入到容器开头,结合借助于下标的随机访问,应该能够发现 vector 是一个非常好用的容器类。

阅读更多:   C++
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif