Lecture Notes for Advanced Programming II

20 November 2001 - Dynamic Memory and Classes


  1. many classes implement dynamic data structures - variable sized data

  2. if at all possible, use the stl

    1. it's all taken care of for you

    2. but, may be expensive in time and space, may not be possible or easy

  3. fixed-size blocks - may be good enough for small amounts of data

    1. not space efficient, but may be time efficient (implementation and run)

    2. not flexible, but reasonably safe with proper checking

    3. also known as pre-allocation

  4. the other possibility is to use dynamic memory - not necessarily new and delete

  5. dynamic memory and classes are not a match made in heaven - worse than dynamic memory and exceptions; leaks o' plenty

    1. three class specific problems - destructors, copying, and assignments

    2. destructors - when an object goes out of scope (perhaps explicitly)

      1. pointers are basic types - they have no destructors

      2. nothing automatically gets done to them on destruction

      3. if nothing gets done to them, they create garbage - unreachable memory

      4. what to do - either handle explicitly in the destructor or wrap them in a class

      5. wrapping them in a class - implementing some kind of garbage collector

        1. complex, mostly effective (until they're not) and powerful

        2. creates a destructor for pointers

        3. this is a common approach - auto pointers, handles, smart pointers and, of course, the stl

        4. this will be taken up in the next section

      6. explicit destructor management - simple, effective

        1. the destructor calls delete on member pointers

        2. no need to check for NULL - a question of style

    3. copying - without care, class copying occurs a lot in c++

      1. base-type values are bit-wise copied

      2. replicates pointer values, leading to un-intentional sharing and dangling pointers on destruction

      3. wrapping works here too, and can be efficient - copy on write

      4. explicitly handle the copy

      5. object copying is implemented by the copy constructor T::T(const T &)

      6. Each block of dynamic memory is replicated in the copy - need to keep that information available

    4. assignment - also bit-wise copies base-type values

      1. assignment is similar to copying, but not that similar

      2. assignment vs. copy - redefinition vs. initialization; the state of the target

      3. despite the syntax, declared variables are initialized; the target state is undefined

      4. in assignment, the target is defined and is redefined - unintentional replication and dangling pointers

      5. deallocate the lhs, then replicate the rhs

      6. assignment and copy constructors usually can share code - duplication code is bad code

      7. two tricks to assignment - self assignment and the assignment expression

        1. self-assignment causes problems - a = a

          1. this does occur, particularly with references

          2. deallocating the lhs also deallocates the rhs

          3. check before doing the assignment - if (&rhs != this)

        2. assignment is an expression - a = b = c

          1. the value of an assignment is the value of the rhs

          2. prototype is T & operator = (const T & rhs)

          3. the return value is return *this;

          4. reference return type is efficient

          5. T operator = (const T & rhs) is more expensive - makes a copy

  6. the rule of three

    1. if you need one of destructors, copy constructors, or assignment, you need them all

    2. classes with visible dynamic memory members need them all

    3. this is non-symmetric, and not hard and fast

      1. a non-empty destructor implies the other two

      2. either the other two may or may not imply the other two


This page last modified on 27 November 2001.