vector
We now introduce C++ Standard Library class template vector
, which is similar to class template array
, but also supports dynamic resizing. Except for the features that modify a vector, the other features shown in Fig. 7.21 also work for array
s. Standard class template vector
is defined in header <vector>
(line 5) and belongs to namespace std
. Chapter 15 discusses the full functionality of vector
. At the end of this section, we’ll demonstrate class vector
’s bounds checking capabilities and introduce C++’s exception-handling mechanism, which can be used to detect and handle an out-of-bounds vector
index.
vector
ObjectsLines 13–14 create two vector
objects that store values of type int
—integers1
contains seven elements, and integers2
contains 10 elements. By default, all the elements of each vector
object are set to 0
. Like array
s, vector
s can be defined to store most data types, by replacing int
in vector<int>
with the appropriate type.
Notice that we used parentheses rather than braces to pass the size argument to each vector
object’s constructor. When creating a vector
, if the braces contain one value of the vector
’s element type, the braces are treated as a one-element initializer list, rather than a call to the constructor that sets the vector
’s size. So the following declaration
vector<int> integers1{7};
actually creates a one-element vector<int>
containing the int
value 7
, not a 7-element vector
.
vector
Member Function size
; Function outputVector
Line 17 uses vector
member function size
to obtain the size (i.e., the number of elements) of integers1
. Line 19 passes integers1
to function outputVector
(lines 95–101), which uses a range-based for
statement to obtain the value in each element of the vector
for output. As with class template array
, you can also do this using a counter-controlled loop and the subscript ([]
) operator. Lines 22 and 24 perform the same tasks for integers2
.
inputVector
Lines 28–29 pass integers1
and integers2
to function inputVector
(lines 104–108) to read values for each vector
’s elements from the user. The function uses a range-based for
statement with a range variable that’s a reference to an int
. Because the range variable is a reference to a vector
element, the reference can be used t store a input value in the corresponding element.
vector
Objects for InequalityLine 40 demonstrates that vector
objects can be compared with one another using the !=
operator. If the contents of two vector
s are not equal, the operator returns true
; otherwise, it returns false
.
vector
with the Contents of AnotherThe C++ Standard Library class template vector
allows you to create a new vector
object that’s initialized with the contents of an existing vector
. Line 46 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’ll learn about copy constructors in detail in Chapter 10. Lines 48–50 output the size and contents of integers3
to demonstrate that it was initialized correctly.
vector
s and Comparing vector
s for EqualityLine 54 assigns integers2
to integers1
, demonstrating that the assignment (=
) operator can be used with vector
objects. Lines 56–59 output the contents of both objects to show that they now contain identical values. Line 64 then compares integers1
to integers2
with the equality (==
) operator to determine whether the contents of the two objects are equal (which they are) after the assignment in line 54.
[]
Operator to Access and Modify vector
ElementsLines 69 and 73 use square brackets ([]
) to obtain a vector
element and use it as an rvalue and as an lvalue, respectively. Recall from Section 5.12 that an rvalue cannot be modified, but an lvalue can. As is the case with array
s, C++ is not required to perform bounds checking when vector
elements are accessed with square brackets.2 Therefore, you 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
(as does class template array
), which we use at line 80 and discuss shortly.
An exception indicates a problem that occurs while a program executes. The name “exception” suggests that the problem occurs infrequently. Exception handling enables you to create fault-tolerant programs that can process (or handle) exceptions. In many cases, this allows a program to continue executing as if no problems were encountered. For example, Fig. 7.21 still runs to completion, even though an attempt was made to access an out-of-range subscript. More severe problems might prevent a program from continuing normal execution, instead requiring the program to notify the user of the problem, then terminate. When a function detects a problem, such as an invalid array
subscript or an invalid argument, it throws an exception—that is, an exception occurs. Here we introduce exception handling briefly. We’ll discuss it in detail in Chapter 17.
try
StatementTo handle an exception, place any code that might throw an exception in a try
statement (lines 78–84). The try
block (lines 78–81) contains the code that might throw an exception, and the catch
block (lines 82–84) contains the code that handles the exception if one occurs. As you’ll see in Chapter 17, you can have many catch
blocks to handle different types of exceptions that might be thrown in the corresponding try
block. If the code in the try
block executes successfully, lines 82–84 are ignored. The braces that delimit try
and catch
blocks’ bodies are required.
The vector
member function at
provides bounds checking and throws an exception if its argument is an invalid subscript. By default, this causes a C++ program to terminate. If the subscript is valid, function at
returns either
a reference to the element at that location—this is a modifiable lvalue that can be used to change the value of the corresponding vector
element, or
a const
reference to the element at that location—this is a nonmodifiable lvalue that cannot be used to change the value of the corresponding vector
element.
A nonmodifiable lvalue is treated as a const
object. If at
is called on a const
array
or via a reference that’s declared const
, the function returns a const
reference.
catch
BlockWhen the program calls vector
member function at
with the argument 15
(line 80), the function attempts to access the element at location 15, which is outside the vector
’s bounds—integers1
has only 10 elements at this point. Because bounds checking is performed at execution time, vector
member function at
generates an exception—specifically line 80 throws an out_of_range
exception (from header <stdexcept>
) to notify the program of this problem. At this point, the try
block terminates immediately and the catch
block begins executing—if you declared any variables in the try
block, they’re now out of scope and are not accessible in the catch
block.
The catch
block declares a type (out_of_range
) and an exception parameter (ex
) that it receives as a reference. The catch
block can handle exceptions of the specified type. Inside the block, you can use the parameter’s identifier to interact with a caught exception object.
Catching an exception by reference increases performance by preventing the exception object from being copied when it’s caught. You’ll see in later chapters that catching by reference is also important when defining catch
blocks that process related exception types.
what
Member Function of the Exception ParameterWhen lines 82–84 catch the exception, the program displays a message indicating the problem that occurred. Line 83 calls the exception object’s what
member function to get the error message that’s stored in the exception object and display it. Once the message is displayed in this example, the exception is considered handled and the program continues with the next statement after the catch
block’s closing brace. In this example, lines 87–91 execute next. We use exception handling again in Chapters 9–12 and Chapter 17 presents a deeper look.
vector
One of the key differences between a vector
and an array
is that a vector
can dynamically grow and shrink as the number of elements it needs to accommodate varies. To demonstrate this, line 87 shows the current size of integers3
, line 88 calls the vector
’s push_back
member function to add a new element containing 1000 to the end of the vector
and line 89 shows the new size of integers3
. Line 91 then displays integers3
’s new contents.
vector
Many of the array
examples in this chapter used list initializers to specify the initial array
element values. C++11 also allows this for vector
s (and other C++ Standard Library data structures).