首页 > 编程笔记 > C++笔记 阅读:268

STL vector用法详解

标准模板库(STL是程序员定义的数据类型和算法的集合,可供 C++ 程序使用。这些数据类型和算法不是 C++ 语言的一部分,但它们的创建是对内置数据类型的有益补充。如果打算继续在计算机科学领域学习,那么就应该熟悉 STL。本节介绍 STL 数据类型之一:矢量(vector)

注意,要使用矢量,则程序的头文件必须指明使用 namespacestd,因为矢量包含在该命名空间中。许多较早的编译器不允许命名空间或不支持 STL。

在 STL 中定义的数据类型通常称为容器。之所以称为容器,是因为它们存储和组织数据。STL 中有两种类型的容器:顺序容器和关联容器:
  1. 顺序容器以序列方式组织数据,类似于数组;
  2. 关联容器使用关键字组织数据,它允许对存储在容器中的元素进行快速随机访问;

vector 数据类型是一个序列容器,它很像一个一维数组,其表现和数组相似的地方如下:
  • 矢量包含一系列值或元素。
  • 矢量将其元素存储在连续的内存位置中。
  • 可以使用数组下标运算符[]访问矢量中的各个元素。

但是,矢量相对于数组还有几个优点,比如说:
  • 不必声明矢量将具有的元素的数量。
  • 如果向已满的矢量添加值,则矢量将自动增加其大小以适应新值。
  • 矢量可以报告它们包含的元素的数量。

vector定义和初始化

要在程序中使用矢量,则必须使用以下语句包含 vector 头文件:

#include <vector>

创建矢量对象的语法与定义一个常规变量或数组所用的语法有所不同。以下是一个例子:

vector<int> numbers;

这个语句将 numbers 定义为一个 int 的矢量。请注意,数据类型包含在尖括号内,紧跟在单词 vector 之后。由于矢量的大小随着添加值而扩大,因此不需要声明大小。不过,如果愿意的话,也可以声明一个开始大小。示例如下:

vector<int> numbers(10);

这个语句将 numbers 定义为 10 个整数的矢量,但这只是一个起始大小。如果添加 10 个以上的值,它的大小将会扩大。

注意,如果为矢量指定开始大小,则大小声明符将被括在圆括号中,而不是方括号。

为矢量指定开始大小时,还可以指定一个初始化值。初始化值被复制到每个元素。示例如下:

vector<int> numbers (10, 2);

在这个语句中,numbers 被定义为 10 个整数的矢量,并且 numbers 中的每个元素都被初始化为值 2。

也可以用另一个矢量中的值初始化一个矢量。例如,如果 set1 是已经有值的 int 矢量,则以下语句将创建一个名为 set2 的新矢量,它是 set1 的精确副本:

vector<int> set2(set1);

在执行这个语句之后,矢量 set2 将具有相同数量的元素,并保持与 set1 相同的一组值。如果使用的是 C++ 11 版本,则还可以使用一个值列表来初始化 vector,示例如下:

vector<int> numbers { 10, 20, 30, 40 };

该语句定义了一个名为 numbers 的 int 矢量。该矢量有 4 个元素,其初始化值为 10, 20, 30 和 40。注意,初始化列表被括在一组大括号中,但是在它前面不使用赋值运算符(=)。表 1 总结了前面讨论的矢量定义过程。

表 1 vector定义示例
定义格式 描 述
vector<string> names; 将 names 定义为 string 对象的空矢量
vector<int> scores (15); 将 scores 定义为 15 个整数的矢量
vector<char> letters (25, 'A'); 将 letters 定义为 25 个字符的矢量。每个元素都用 'A' 初始化
vector<double> values2(values1); 将 values2 定义为 double 矢量。value1 的所有元素(也是 double 矢量)将被复制到 value2
vector<int> length{12, 10, 6}; 在 C++ 11 中,该语句定义 length 为 3 个 int 值的矢量,保存值 12、10 和 6

存储和检索 vector 中的值

要将值存储到已存在的矢量元素中,或访问矢量元素中存储的数据,可以使用数组下标运算符 []。下面的程序演示了该操作:
//This program stores employee hours worked
// and hourly pay rates in two parallel vectors.
#include <iostream>
#include <iomanip>
#include <vector>    // Needed to use vectors
using namespace std;

int main()
{
    const int NUM_EMPS = 5;    // Number of employees
    vector <int> hours(NUM_EMPS);    // Define a vector of integers
    vector <double> payRate(NUM_EMPS); // Define a vector of doubles
    double grossPay;    // An employee's gross pay
   
    // Get employee work data
    cout << "Enter the hours worked and hourly pay rates of " << NUM_EMPS << " employees. \n";
    for (int index = 0; index < NUM_EMPS; index++)
    {
        cout <<"\nHours worked by employee #" << (index + 1) << ": ";
        cin >> hours[index];
        cout << "Hourly pay rate for employee #" << (index +1) << ": ";
        cin >> payRate[index];
    }
    //Display each employeeA s gross pay
    cout << "\nHere is the gross pay for each employee: \n" ;
    cout << fixed << showpoint << setprecision (2);
    for (int index = 0; index < NUM_EMPS; index++)
    {
        grossPay = hours[index] * payRate[index];
        cout << "Employee #" << (index + 1);
        cout << ": $" << setw(7) << grossPay << endl;
    }
    return 0;
}
程序输出结果为:

Enter the hours worked and hourly pay rates of 5 employees.

Hours worked by employee #1: 10
Hourly pay rate for employee #1: 9.75

Hours worked by employee #2: 15
Hourly pay rate for employee #2: 8.62

Hours worked by employee #3: 20
Hourly pay rate for employee #3: 10.50

Hours worked by employee #4: 40
Hourly pay rate for employee #4: 18.75

Hours worked by employee #5: 40
Hourly pay rate for employee #5: 15.65

Here is the gross pay for each employee:
Employee #1: $  97.50
Employee #2: $ 129.30
Employee #3: $ 210.00
Employee #4: $ 750.00
Employee #5: $ 626.00

下面来分析程序中的某些代码。首先看第 5 行,它包含使用矢量所必需的预处理器指令:

#include <vector>

在第 11 行和第 12 行中的以下语句定义了两个矢量:

vector<int> hours (NUM_EMPS) ;    // 定义整数矢量
vector<double> payRate (NUM_EMPS) ;    // 定义双精度类型矢量

在第 17 行 for 循环开始,它的目的是输入用户数据。在第 20 行和第 22 行,循环使用了相同的语句,读取输入并将它们放入矢量元素中,这些矢量元素由循环控制变量 index 的当前值指定。

由于在每个矢量名称后面跟着一个大小声明符,所以这两个矢量都将按指定的大小创建。在此示例中,命名常量 NUM_EMPS 等于 5,所以两个矢量一开始都有 5 个元素。因为它们已经有元素了,所以可以使用 [] 运算符从元素中读取值或给元素赋值,这与使用数组元素的方式完全一样。

cin >> hours[index];
cin >> payRate [index];

在第 27 行中开始第 2 个 for 循环,它的目的是计算并显示每个员工的总收入。在第 29 行,该循环的语句执行该计算,使用的数据来自于每个矢量的特定元素。

grossPay = hours[index] * payRate[index];

只要矢量已经定义并且拥有给定的起始元素,就可以像使用数组一样访问它们,存储和检索其数据。

遍历vector

在 C++11 版本中,程序员可以使用基于范围的 for 循环遍历矢量中的元素,下面的程序演示了其用法:
// This program uses two range-based for loops with a vector.
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    // Define a vector with a starting size of 5 elements
    vector<int>numbers(5);
    // Get values for the vector elements
    // Make the range variable a reference variable so it can be
    // used to change the contents of the element it references.
    for (int &val : numbers)
    {
        cout << "Enter an integer value: ";
        cin >> val;
    }

    // Display the vector elements
    cout << "\nHere are the values you entered: \n";
    for (int val : numbers)
        cout <<val <<" ";
    cout << endl;
    return 0;
}
程序输出结果:

Enter an integer value: 10
Enter an integer value: 20
Enter an integer value: 30
Enter an integer value: 40
Enter an integer value: 50

Here are the values you entered:
10 20 30 40 50

vector push_back 成员函数

不能使用 [] 运算符来访问尚不存在的矢量元素。要将值存储在没有起始大小或已满的矢量中,应使用 push_back 成员函数。该函数接受一个值作为实参,并将其存储在位于矢量末尾的新元素中。

以下是一个使用 push_back 函数,将一个元素添加到一名为 numbers 的 int 矢量的例子:

numbers.push_back(25);

该语句可以创建一个新的元素,其存储的值为 25,该元素被放在 numbers 矢量的末尾。如果 numbers 以前没有元素,则新元素将成为其单一元素。

下面的程序允许用户指定员工的数量。hours 和 payRate 这两个矢量并没有定义开始大小。由于这些矢量没有起始元素,因此需要使用 push_back 成员函数来存储值。
// This program stores employee hours worked and hourly pay rates
// in two vectors. It demonstrates the use of the push_back member
// function to add new elements to the vectors.
#include <iostream>
#include <iomanip>
#include <vector>
// Needed to use vectors

using namespace std;

int main()
{
    vector<int> hours;    // hours is an empty integer vector
    vector<double> payRate; // payRate is an empty double vector
    double grossPay;
    int numEmp1oyees;    // Number of employees
    int index;    // Loop counter

    // Get the number of employees
    cout << "How many employees do you have?";
    cin >> numEmp1oyees;
    // Input the payroll data
    cout << "Enter the hours worked and hourly pay rates of the "<< numEmployees << " employees. \n" ;
    for (index = 0; index < numEmployees; index++)
    {
        int tempHours;    // Number of hours entered
        double tempRate; 丨丨 Pay rate entered
        cout << "Hours worked by employee #" << (index + 1) << ":";
        cin >> tempHours;
        hours.push_back(tempHours); // Add an element to hours
        cout << "Hourly pay rate for employee #" << (index + 1) << ": ";
        cin >> tempRate;
        payRate.push_back(tempRate); // Add an element to payRate
    }

    //Display each employeeT s gross pay
    cout << "\nHere is the gross pay for each employee: \n";
    cout << fixed << showpoint << setprecision (2);
    for (index = 0; index < numEmployees; index++)
    {
        grossPay = hours[index] * payRate[index];
        cout << "Employee #" << (index + 1);
        cout << " $" << setw (7) << grossPay << endl;
    }
    return 0;
}
程序输出结果:

How many employees do you have?3
Enter the hours worked and hourly pay rates of the 3 employees.
Hours worked by employee #1:40
Hourly pay rate for employee #1: 12.63
Hours worked by employee #2:25
Hourly pay rate for employee #2: 10.35
Hours worked by employee #3:45
Hourly pay rate for employee #3: 22.65

Here is the gross pay for each employee:
Employee #1 $ 505.20
Employee #2 $ 258.75
Employee #3 $1019.25

程序中第 39〜44 行中的循环可以计算并显示每个员工的总收入,它使用 [] 运算符来访问 hours 和 payRate 矢量的元素。之所以可以这样做,是因为第 24〜34 行中的第一个循环已经使用了 push_back 成员函数来创建两个矢量中的元素。

vector size成员函数

与数组不同,矢量可以报告它们包含的元素的数量,这是通过 size 成员函数实现的。以下是一个使用 size 成员函数的示例:

numValues = set.size();

在该语句中,假定 numValues 是一个 int,set 是一个矢量。执行语句后,numValues 将包含 set 中的元素数量。

在编写接收矢量作为实参的函数时,size 成员函数特别有用。例如,来看 showValues 函数的以下代码:
void showValues(vector<int> vect)
{
    for (int count = 0; count < vect.size(); count++)
        cout << vect[count] << endl;
}
因为矢量可以报告其大小,所以该函数不需要第二个参数来表示矢量中元素的个数。下面的程序演示了该函数的应用:
//This program demonstrates the vector size member function.
#include <iostream>
#include <vector>
using namespace std;

// Function prototype

void showValues(vector<int>);

int main()
{
    vector<int> values;
    // Store a series of numbers in the vector
    for (int count = 0; count < 7; count++)
        values.push_back(count * 2);
    // Display the numbers
    showValues(values);
    return 0;
}
void showValues(vector<int> vect)
{
    for (int count = 0; count < vect.size(); count++)
        cout << vect[count] << " ";
    cout << endl;
}
程序输出结果:

0 2 4 6 8 10 12

程序中在定义矢量时,并未给定元素,所以在将值存储到矢量中时,使用了 push_back 函数。每次被调用时,push_back 函数都将创建一个新的矢量元素来存储值。

vector pop_back成员函数

要从矢量中删除最后一个元素,可以使用 pop_back 成员函数。以下语句从名为 collection 的矢量中移除最后一个元素:

collection.pop_back();

下面的程序演示了 pop_back 函数:
//This program demonstrates the vector size,
//push_back, and pop_back member functions.
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> values;
    // Store values in the vector
    values.push_back(1);
    values.push_back(2);
    values.push_back(3);
    cout << "The size of values is " << values.size () << endl;
    // Remove a value from the vector
    cout << "Popping a value from the vector...\n";
    values.pop_back();
    cout << "The size of values is now " << values.size () << endl;
    // Now remove another value from the vector
    cout << "Popping a value from the vector...\n";
    values.pop_back();
    cout << "The size of values is now " << values.size() << endl;
    // Remove the last value from the vector
    cout << "Popping a value from the vector...\n"; values.pop_back();
    cout << "The size of values is now " << values.size () << endl;
    return 0;
}
程序输出结果:

The size of values is 3
Popping a value from the vector...
The size of values is now 2
Popping a value from the vector...
The size of values is now 1
Popping a value from the vector...
The size of values is now 0

注意,pop_back 函数是一个 void 函数,它不返回将从矢量中删除的值。以下代码行将不起作用:

cout << "The value being removed from the vector is "<<values.pop_back() << endl; // Error!

vector clear成员函数

要完全清除矢量的内容,可以使用 clear 成员函数,如下例所示:

numbers.clear();

在执行该语句之后,numbers 的所有元素都将被清除。下面的程序演示了该函数的用法:
//This program demonstrates the vector clear member function.
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> values(100);
    cout << "The values vector has " << values.size() << " elements.\n";
    cout << "will call the clear member function. . . \n";
    values.clear();
    cout << "Now the values vector has "<< values.size() << " elements . \n";
    return 0;
}
程序输出结果:

The values vector has 100 elements.
will call the clear member function. . .
Now the values vector has 0 elements .

vector empty成员函数

要确定一个矢量是否为空,可以使用 empty 成员函数。如果矢量为空,则该函数将返回 true;如果矢量中存储有元素,则返回 false。假设 numberVector 是一个矢量,以下是其应用示例:
if (numberVector.empty())
    cout << "No values in numberVector. \n";
下面的程序显示了如何传递一个矢量给函数。该函数名为 avgVector,演示了 empty 成员函数的用法。
//This program demonstrates the vector empty member function.
#include <iostream>
#include <vector>
using namespace std;

// Function prototype
double avgVector(vector<int>);

int main()
{
    vector<int> values;    // Define a vector to hold int values
    int numValues;    // Number of values to be averaged
    double average;    // Average of the stored values
    //Get the number of values    to average
    cout << "How many values do you wish to average?";
    cin >> numValues;
    // Get the values and store    them in a vector
    for (int count = 0; count <    numValues; count++)
    {
        int tempValue;
        cout << "Enter an integer value:";
        cin >> tempValue;
        values.push_back(tempValue);
    }
    // Get the average of the values and display it
    average = avgVector(values);
    cout << "Average: " << average << endl;
    return 0;
}

double avgVector(vector<int> vect)
{
    int total = 0;    // Accumulator
    double avg = 0.0;
    if (vect.empty())    // Determine if the vector is empty
        cout << "No values to average. \n";
    else
    {
        for (int count = 0; count < vect.size(); count++)
            total += vect[count];
            avg = static_cast<double>(total)/vect.size();
    }
    return avg;
}
程序输出结果:

How many values do you wish to average?4
Enter an integer value:12
Enter an integer value:3
Enter an integer value:7
Enter an integer value:9
Average: 7.75

vector成员函数汇总

表 2 提供了有关矢量成员函数的汇总信息,其中有一些在已经讨论过,另外还有一些是新添加的。

表 2 vector成员函数汇总
成员函数 描 述
at(position) 返回 vector 中位于 position 位置的兀素的值。示例:
x = vect. at (5) ; //将 vect [5] 的值赋给 x
capacity() 返回在不重新分配额外内存的情况下,可能存储在矢量中的最大元素数量(它和由 size 成员函数返回的值并不是一回事)。示例:
x = vect. capacity () ; //将 vect 的容量赋值给 x
clear() 清除矢量的所有元素。示例:
vect .clear () ; //从 vect 中移除所有兀素
empty() 如果 vector 是空的,则返回 true。否则,它返回 false。示例:
if (vect. empty () ; //如果该矢量是空的
    cout << "The vector is empty.";
pop_back() 从矢量中删除最后一个元素。示例:
vect.pop_back () ; //移除 vect 的最后一个元素,大小减去1
push_back(value) 在矢量的最后一个元素中存储一个值。如果矢量已满或为空,则会创建一个 新元素。示例:
vect.push_back (7) ; //在 vect 的最后一个元素中存储 7
reverse() 反转矢量中元素的顺序(最后一个元素变成第一个元素,第一个元素成为最后一个元素)。示例:
vect. reverse () ; //反转 vect 中元素的顺序
resize(n)
resize(n, value)
调整矢量的大小以使其具有 n 个元素,其中 n 大于矢量的当前大小。如果包含可选的参数 value,则每个新元素都将使用该 value 值进行初始化。 vect 当前已有 4 个元素情况下的示例:
vect. resize (6, 99) ; //将两个元素添加到矢量的末尾,每个元素初始化为 99
size() 返回矢量中元素的数量。示例:
numElements = vect.size();
swap(vector2) 将矢量的内容与 vector2 的内容交换。示例:
vect1.swap (vect2) ; //交换 vect1 和 vect2 的内容