CS 509, Advanced Programming II

Fall 2003 - Test 4


  1. Explain why the code

    int * invalid_pointer() {
      int x;
      return &x;
      }
    

    causes instant disaster (according to Koenig and Moo), but the code

    int * valid_pointer() {
      static int x;
      return &x;
      }
    

    does not.


    invalid_pointer() returns a pointer to a variable that exists only while the function is executing. Once the function returns, x ceases to exist, and the pointer returned now points to hyperspace (or, more accurately and insidiously, points to where x used to be, which will look o.k. until something else occupies x's space). See Section 10.6 in Koening and Moo for more information.

    A number of people wrote that the problem occurs because x is unitinialized. This is true, but that problem occurs in both functions, which the question asks about something that's wrong in one function but write in the other.


  2. Given the (partial) class

    class Str {
      public:
        template < class In >
        Str(In b, In e) {
          std::copy(b, e, std::back_inserter(data));
          }
      private:
        vector<char> data;
      };
    

    Explain why the range constructor is a template function.


    Iterators are part of a particular container; each container defines a different iterator. Without function templates, you'd have to define a range constructor for every possible iterator:

    Str(std::vector<char>::iterator b, std::vector<char>::iterator e) {
      std::copy(b, e, std::back_inserter(data));
      }
    
    Str(std::list<char>::iterator b, std::list<char>::iterator e) {
      std::copy(b, e, std::back_inserter(data));
      }
    
    Str(char * b, char * e) {
      std::copy(b, e, std::back_inserter(data));
      }
    

    There were a lot of generic answers to this question, as in "The constructor uses a template parameter because the type of the arguments doesn't matter." In addition to being generic, it's not quite correct because types do matter; for example, you can't pass in booleans.


  3. Many of your colleagues attempted to solve the fourth assignment by searching the photograph for an identical configuration of angles taken from the trace. For example, if the trace formed a isosceles right triangle, the code would look for triplets in the photograph that formed one 90- and two 45-degree angles.

    Describe a test case that demonstrates how this approach can lead to incorrect answers.


    The test case is

    0 0 1  2 0 1  2 1 1  0 1 1
    box 0 0  1 0  1 1  0 1 
    

    The photograph shows a rectangle of height 1 and width 2; the trace is of a square. Both have four right angles, but a box doesn't match a rectangle.

    Almost everybody tried to answer this question using the example given in the question. Unfortunately, using matching angles works when the trace has three points; it's only when you move to traces with more than three points that the problems begin.


  4. The following code compiles successfully

    void time::add() {
      increase();
      }
    

    The following code doesn't compile successfully:

    int main() {
      time t;
      t.increase();  // error here.
      }
    

    Show the declaration (not definition) of time.

    (Here's a hint: this question has a correct answer.)


    From main() we can conclude increase() is, or should be, a member function of the time class. From time::add() we can conclude that increase() is a member function of time, and that main() is calling it correctly.

    We can conclude that time::add() is allowed to call increase() but main() is not; that is, increase() has non-public access permissions.

    The answers to this question was all over the place.



This page last modified on 25 November 2003.