Object-Oriented Programming

CSCI-UA.0470-001

NYU, Undergraduate Division, Computer Science Course - Fall 2013

OOP Class Notes for 11/12/13

Explicit Memory Management in C++: The Law of the Big Three

The Big Three: Copy Constructor, Destructor, and Assignment Operator

The law is: if your class requires a copy constructor, destructor, or assignment operator, it is likely to require all three!

Value Semantics vs. Reference Semantics

  • The int type in java uses value semantics.
    • Why is that great?
    • You can manipulate it without worrying about other variables, very localized
    • some languages only have value semantics for this reason
  • strings in many programming language have reference semantics
    • The program doesn't know the size of the string, so it cannot be allocated to stack
    • must be put on heap, thus forced to have references

let's write a C++ class that encapsulates a string with value semantics.

  • this code will follow the law of the big three!
  • copy constructer is needed to pass stringval instances as parameters in a function
  • destructor is needed because it's being stored on the heap - without it the program will not free up memory
  • assignment operator is needed to overwrite the default C++ assignment to copy the contents only
    • when no operator is defined, it will copy the context of the instance
    • so if you make a copy, it will copy the pointer to data instead of creating a new copy (shallow copy)
    • this will cause a memory leak as it overwrites the old pointer
    • it will also cause the char arrays to be shared between different stringval instances, which will complicate memory management.
  • Copy constructor - get length of the C-string in other, set data to be a new array of char of that length, then copy contents of other.data into data
  • stringval::stringval(const stringval& other) 
      : len(other.len), data(new char[len]) {
      TRACE();
      memcpy(data, other.data, len);
    }
  • Destructor - needs to clean up the heap! delete data
  • stringval::~stringval() {
      TRACE();
      delete[] data;
    }
  • Assignment operator - like destructor combined with copy constructor
    • deallocate the memory for the current C-string before copying the C-string from other
    • after deleting data, you need to reallocate a new char[] of appropriate length before copying
    • No self-assignment! Check to make sure data and other.data are not identical. Otherwise the C-string will be deleted before it is copied.
  • stringval& stringval::operator=(const stringval& other) {
      TRACE();
      if (data != other.data) {
        delete[] data;
        len = other.len;
        data = new char[len];
        memcpy(data, other.data, len);
      }
      return *this;
    }