Introduction to C++ Standard Library Class Template vector

We now introduce C++ Standard Library class template vector, which represents a more robust type of array featuring many additional capabilities. As you will see in later chapters and in more advanced C++ courses, C-style pointer-based arrays (i.e., the type of arrays presented thus far) have great potential for errors. For example, as mentioned earlier, a program can easily "walk off" either end of an array, because C++ does not check whether subscripts fall outside the range of an array. Two arrays cannot be meaningfully compared with equality operators or relational operators. As you will learn in Chapter 8, pointer variables (known more commonly as pointers) contain memory addresses as their values. Array names are simply pointers to where the arrays begin in memory, and, of course, two arrays will always be at different memory locations. When an array is passed to a general-purpose function designed to handle arrays of any size, the size of the array must be passed as an additional argument. Furthermore, one array cannot be assigned to another with the assignment operator(s)array names are const pointers, and, as you will learn in Chapter 8, a constant pointer cannot be used on the left side of an assignment operator. These and other capabilities certainly seem like "naturals" for dealing with arrays, but C++ does not provide such capabilities. However, the C++ Standard Library provides class template vector to allow programmers to create a more powerful and less error-prone alternative to arrays. In Chapter 11, Operator Overloading; String and Array Objects, we present the means to implement such array capabilities as those provided by vector. You will learn how to customize operators for use with your own classes (a technique known as operator overloading).

The vector class template is available to anyone building applications with C++. The notations that the vector example uses might be unfamiliar to you, because vectors use template notation. Recall that Section 6.18 discussed function templates. In Chapter 14, we discuss class templates. For now, you should feel comfortable using class template vector by mimicking the syntax in the example we show in this section. You will deepen your understanding as we study class templates in Chapter 14. Chapter 23 presents class template vector (and several other standard C++ container classes) in detail.

The program of Fig. 7.26 demonstrates capabilities provided by C++ Standard Library class template vector that are not available for C-style pointer-based arrays. Standard class template vector provides many of the same features as the Array class that we construct in Chapter 11, Operator Overloading; String and Array Objects. Standard class template vector is defined in header <vector> (line 11) and belongs to namespace std (line 12). Chapter 23 discusses the full functionality of standard class template vector.

Figure 7.26. C++ Standard Library class template vector.

(This item is displayed on pages 373 - 376 in the print version)

1 // Fig. 7.26: fig07_26.cpp 2 // Demonstrating C++ Standard Library class template vector. 3 #include 4 using std::cout; 5 using std::cin; 6 using std::endl; 7 8 #include 9 using std::setw; 10 11 #include 12 using std::vector; 13 14 void outputVector( const vector< int > & ); // display the vector 15 void inputVector( vector< int > & ); // input values into the vector 16 17 int main() 18 { 19 vector< int > integers1( 7 ); // 7-element vector< int > 20 vector< int > integers2( 10 ); // 10-element vector< int > 21 22 // print integers1 size and contents 23 cout << "Size of vector integers1 is " << integers1.size() 24 << " vector after initialization:" << endl; 25 outputVector( integers1 ); 26 27 // print integers2 size and contents 28 cout << " Size of vector integers2 is " << integers2.size() 29 << " vector after initialization:" << endl; 30 outputVector( integers2 ); 31 32 // input and print integers1 and integers2 33 cout << " Enter 17 integers:" << endl; 34 inputVector( integers1 ); 35 inputVector( integers2 ); 36 37 cout << " After input, the vectors contain: " 38 << "integers1:" << endl; 39 outputVector( integers1 ); 40 cout << "integers2:" << endl; 41 outputVector( integers2 ); 42 43 // use inequality (!=) operator with vector objects 44 cout << " Evaluating: integers1 != integers2" << endl; 45 46 if ( integers1 != integers2 ) 47 cout << "integers1 and integers2 are not equal" << endl; 48 49 // create vector integers3 using integers1 as an 50 // initializer; print size and contents 51 vector< int > integers3( integers1 ); // copy constructor 52 53 cout << " Size of vector integers3 is " << integers3.size() 54 << " vector after initialization:" << endl; 55 outputVector( integers3 ); 56 57 // use overloaded assignment (=) operator 58 cout << " Assigning integers2 to integers1:" << endl; 59 integers1 = integers2; // integers1 is larger than integers2 60 61 cout << "integers1:" << endl; 62 outputVector( integers1 ); 63 cout << "integers2:" << endl; 64 outputVector( integers2 ); 65 66 // use equality (==) operator with vector objects 67 cout << " Evaluating: integers1 == integers2" << endl; 68 69 if ( integers1 == integers2 ) 70 cout << "integers1 and integers2 are equal" << endl; 71 72 // use square brackets to create rvalue 73 cout << " integers1[5] is " << integers1[ 5 ]; 74 75 // use square brackets to create lvalue 76 cout << " Assigning 1000 to integers1[5]" << endl; 77 integers1[ 5 ] = 1000; 78 cout << "integers1:" << endl; 79 outputVector( integers1 ); 80 81 // attempt to use out-of-range subscript 82 cout << " Attempt to assign 1000 to integers1.at( 15 )" << endl; 83 integers1.at( 15 ) = 1000; // ERROR: out of range 84 return 0; 85 } // end main 86 87 // output vector contents 88 void outputVector( const vector< int > &array ) 89 { 90 size_t i; // declare control variable 91 92 for ( i = 0; i < array.size(); i++ ) 93 { 94 cout << setw( 12 ) << array[ i ]; 95 96 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output 97 cout << endl; 98 } // end for 99 100 if ( i % 4 != 0 ) 101 cout << endl; 102 } // end function outputVector 103 104 // input vector contents 105 void inputVector( vector< int > &array ) 106 { 107 for ( size_t i = 0; i < array.size(); i++ ) 108 cin >> array[ i ]; 109 } // end function inputVector  

Size of vector integers1 is 7 vector after initialization: 0 0 0 0 0 0 0 Size of vector integers2 is 10 vector after initialization: 0 0 0 0 0 0 0 0 0 0 Enter 17 integers: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 After input, the vectors contain: integers1: 1 2 3 4 5 6 7 integers2: 8 9 10 11 12 13 14 15 16 17 Evaluating: integers1 != integers2 integers1 and integers2 are not equal Size of vector integers3 is 7 vector after initialization: 1 2 3 4 5 6 7 Assigning integers2 to integers1: integers1: 8 9 10 11 12 13 14 15 16 17 integers2: 8 9 10 11 12 13 14 15 16 17 Evaluating: integers1 == integers2 integers1 and integers2 are equal integers1[5] is 13 Assigning 1000 to integers1[5] integers1: 8 9 10 11 12 1000 14 15 16 17 Attempt to assign 1000 to integers1.at( 15 ) abnormal program termination  

Lines 1920 create two vector objects that store values of type intintegers1 contains seven elements, and integers2 contains 10 elements. By default, all the elements of each vector object are set to 0. Note that vectors can be defined to store any data type, by replacing int in vector< int > with the appropriate data type. This notation, which specifies the type stored in the vector, is similar to the template notation that Section 6.18 introduced with function templates. Again, Chapter 14 discusses this syntax in detail.



Line 23 uses vector member function size to obtain the size (i.e., the number of elements) of integers1. Line 25 passes integers1 to function outputVector (lines 88102), which uses square brackets ([]) to obtain the value in each element of the vector as a value that can be used for output. Note the resemblance of this notation to the notation used to access the value of an array element. Lines 28 and 30 perform the same tasks for integers2.

Member function size of class template vector returns the number of elements in a vector as a value of type size_t (which represents the type unsigned int on many systems). As a result, line 90 declares the control variable i to be of type size_t, too. On some compilers, declaring i as an int causes the compiler to issue a warning message, since the loop-continuation condition (line 92) would compare a signed value (i.e., int i) and an unsigned value (i.e., a value of type size_t returned by function size).

Lines 3435 pass integers1 and integers2 to function inputVector (lines 105109) to read values for each vector's elements from the user. Function inputVector uses square brackets ([]) to obtain lvalues that can be used to store the input values in each element of the vector.

Line 46 demonstrates that vector objects can be compared directly with the !=operator. If the contents of two vectors are not equal, the operator returns true; otherwise, the operator returns false.

C++ Standard Library class template vector allows programmers to create a new vector object that is initialized with the contents of an existing vector. Line 51 creates a vector object (integers3) and initializes it with a copy of integers1. This invokes vector's so-called copy constructor to perform the copy operation. You will learn about copy constructors in detail in Chapter 11. Lines 53 and 55 output the size and contents of integers3 to demonstrate that it was initialized correctly.

Line 59 assigns integers2 to integers1, demonstrating that the assignment (=) operator can be used with vector objects. Lines 62 and 64 output the contents of both objects to show that they now contain identical values. Line 69 then compares integers1 to integers2 with the equality (==) operator to determine whether the contents of the two objects are equal after the assignment in line 59 (which they are).

Lines 73 and 77 demonstrate that a program can use square brackets ([]) to obtain a vector element as an unmodifiable lvalue and as a a modifiable lvalue, respectively. An unmodifiable lvalue is an expression that identifies an object in memory (such as an element in a vector), but cannot be used to modify that object. A modifiable lvalue also identifies an object in memory, but can be used to modify the object. As is the case with C-style pointer-based arrays, C++ does not perform any bounds checking when vector elements are accessed with square brackets. Therefore, the programmer must ensure that operations using [] do not accidentally attempt to manipulate elements outside the bounds of the vector. Standard class template vector does, however, provide bounds checking in its member function at, which "throws an exception" (see Chapter 16, Exception Handling) if its argument is an invalid subscript. By default, this causes a C++ program to terminate. If the subscript is valid, function at returns the element at the specified location as a modifiable lvalue or an unmodifiable lvalue, depending on the context (non-const or const) in which the call appears. Line 83 demonstrates a call to function at with an invalid subscript.


In this section, we demonstrated the C++ Standard Library class template vector, a robust, reusable class that can replace C-style pointer-based arrays. In Chapter 11, you will see that vector achieves many of its capabilities by "overloading" C++'s built-in operators, and you will learn how to customize operators for use with your own classes in similar ways. For example, we create an Array class that, like class template vector, improves upon basic array capabilities. Our Array class also provides additional features, such as the ability to input and output entire arrays with operators >> and <<, respectively.

Категории