hdr(2, Test 1 - Vectors) hdr(3, DEPT() CNO(), CTITLE(), Summer 2000)


  1. Briefly describe the behavior of each of the following STL sequence container member functions:
    size()
    max_size()
    reserve(n)
    capacity()
    Make sure you indicate the relations among the member functions (does, for example, capacity() affect size()? If so, how?)


    The c.size() member function returns the number of values stored in the container c. c.size() is a constant function, so it doesn't effect anything in c; c.size() will always be less than or equal to c.capacity().

    The c.max_size() member function returns the largest number of values the container c will ever hold. c.max_size() is a constant function, so it doesn't effect anything in c; c.capacity() will always be less than or equal to c.max_size().

    The c.reserve(n) member function makes sure c has enough space to hold at least n values. If c.capacity() < n, then c.reserve(n) will change c by allocating more space to ensure c.capacity() >= n. After the call c.reserve(n), c.capacity() will be at least n, assuming n is at most c.max_size() and you don't run out of storage.

    The c.capacity() member function returns the number of values c can hold without allocating more storage. c.capacity() is a constant function, so it doesn't effect anything in c; c.capacity() is always at least c.size().

    For more information, see page 270 in Nyhoff.


  2. A colleague of yours has written the following program
    $ cat t1q1p.cc
    #include <vector>
    #include <iostream>
    
    int main (void) {
    
      vector<int> v(1);
      v[0] = 6;
      v.push_back (42);
    
      cerr << "v.size() = " << v.size () << "  " << v[0] << "  " << v[1] << endl;
    
      vector<int> w;
      w.reserve(1);
      w[0] = 6;
      w.push_back(42);
    
      cerr << "w.size() = " << w.size () << "  " << w[0] << "  " << w[1] << endl;
    
      return 0;
      }
    
    $
    
    and got got the following results when the program was compiled and run
    $ g++ -o t1q1p -ansi -pedantic -Wall t1q1p.cc
    
    $ t1q1p
    v.size() = 2  6  42
    w.size() = 1  42  0
    
    $ 
    
    Your colleague is mystified by the program's output, recognizing your expertise in STL, comes to you for an explanation. What is your explanation for the program's behavior?


    Taking the first set of three statements first:

    vector<int> v(1)Create a vector of size 1; the value stored in v is 0, the default value for integers.
    v[0] = 6Replace the default value with the value 6; v's size remains at 1.
    v.push_back(42)Add the value 42 to the end of v, increasing v's size by one to 2.
    The first cout statement then prints v's size (2), the value stored in v's first element (6) and the value stored in v's second element (42).

    vector<int> wCreate a vector of size 0.
    w.reserve(1)Make sure w has enough space to store one value. This statement does not add a value to w, nor does it change w's size, which is still 0.
    w[0] = 6This statement is the problem. It changes the first value stored in w to 6, but there are no values stored in w. Remember, vector access via [] is just as it is for arrays: unchecked and does not change the vector size.
    w.push_back(42)Add the value 42 to the end of w, increasing w's size by one to 1.
    The second cout statement then prints v's size (1), the value stored in v's first element (42) and then whatever random value happens to be stored in v's second element (0 in this case).


  3. Given the definitions
    vector<T> tvec(10, T());
    vector<T>::iterator tveci = tvec.begin();
    
    explain the difference between the expression *(tveci + 1) and the expression (*tveci + 1). You may assume that everything's defined and working.


    (*tveci + 1): The iterator tveci can be thought of as having type pointer to T. Applying the follow operator * to tveci results in a value of type T; adding 1 results in another value of type T.

    *(tveci + 1): Adding 1 to tveci results in an iterator referencing the next (that is, adjacent to the right) value stored in tvec. Applying * to that iterator results in a value of type T.


  4. Let s and e be random iterators from the same sequential container. Suppose the valid iterator range (s, e) is empty (in the sense of the empty() member function). Write a true boolean expression (that is, a relational expression) that describes the way the values of s and e are related.


    Under the usual STL interpretation of an iterator range, e points to the value just after the range. If s points to any value to the left of the value pointed to by e, the iterator range wouldn't be empty. This means the relational expression should check that s is not to the left of e, or s >= e; the stronger relational expression s == e is also acceptable.

    Alternatively, because (s, e) is empty, it contains no values and (e - s) == 0.



This page last modified on 15 i2m(08) 2000.