title: C++ Programming exercise -- Deep Copy
body: <p>I'm trying to create a basic ArrayList implementation in C++ for class.  The course's requirements are quite restrictive, and the data members and functions are required.  However, when I run this, I get "Unable to access memory location", when it tries to delete the list pointer in deepCopy.  I can't seem to figure out why.  Please help.  Thanks!</p>
  
  <h1>Edit:</h1>
  
  <p>I've narrowed the code down.  I still want to give you enough information to be able to help, though.</p>
  
  <h1>Edit #2</h1>
  
  <p>US requested the full code, so I've added it back.</p>
  
  <h2>List.h</h2>
  
  <pre><code>#ifndef LIST_H
  #define LIST_H
  
  /**
  * This implentation of list is a pseudo ArrayList.  Since we don't guarantee that a class has a hashCode in C++
  * this will only work for objects which have an id field.
  *
  */
  template &lt;class T&gt;
  class List{
      private:
                                                  // If you want the max size of the list (100), then you should probably create a const. Example:
                                                  // const int MAX_SIZE;
                                                  // T[] list = new T[MAX_SIZE];
  
                                                  // But really, that is not much better.  This is just bad, overall.  It's like we're implementing a very poor ArrayList.
  
          T * list;                               // This is our array for our elements.
          int numberInList;                       // 
          int listSize;                           // Getter method will be getMaxSize.  This seems unnecessary if we're initializing it to 100...
          int nextIndex;                          // this is a number of the index for the next element.  Really, this should be inside a private class (who has the pointer to its next).
          double loadFactor;                      // We need to determine when we need to allocate additional slots so we don't run out if they try to add more than they have allocated.
          void deepCopy(const List&lt;T&gt; &amp; toBeCopied ); // We need a method to perform a deepCopy.  Abstracts the implementation from each method. Private because we don't want it exposed to clients.
          bool isAboveThreshold();                // Check if the list is above the loadFactor.
  
      // Publicly available API
      public:
          List();
          List(int size);                         // Overloaded constructor to initialize the List to a runtime size
          List(const List&lt;T&gt; &amp; toBeCopied);       // Copy constructor
          ~List();                                // Destructor -- Get rid of the dynamically allocated member.
          T next();                               // Gets the next element in the list, and increments next
          bool add( T &amp; element );                // Adds an element to the list.  Also checks to make sure the element hasn't already been added.
          bool contains(T &amp; element);             // Checks the list to see if the element exists in the list already.
          int getSize();                          // return the number of elements in the list.
          List&lt;T&gt; &amp; List&lt;T&gt;::operator =( const List&lt;T&gt; &amp; toBeCopied );
  };
  
  template &lt;class T&gt;
  List&lt;T&gt;::List(){
      listSize = 100;
      list = new T[listSize];
      numberInList = 0;
      nextIndex = 0;                              // Initialize the next element to 0.
      loadFactor = 0.75;
  };
  
  template &lt;class T&gt;
  List&lt;T&gt;::List(int size){
      list = new T[size];
      numberInList = 0;
      nextIndex = 0;                              // Initialize the next element to 0.
      listSize = size;
      loadFactor = 0.75;
  };
  
  template &lt;class T&gt;
  List&lt;T&gt;::List(const List&lt;T&gt; &amp; toBeCopied){
      deepCopy(toBeCopied);
  };
  
  /****
  *
  * We need to release the allocated heap memory.  Non-pointer members will be deallocated when they are out of scope.
  *
  */
  template &lt;class T&gt;
  List&lt;T&gt;::~List(){
      delete [] list;
  };
  
  /**
  * Return the number of elements in the list.
  */
  template &lt;class T&gt;
  int List&lt;T&gt;::getSize(){
      return numberInList;
  }
  
  /**
  * Return the number of elements in the list.
  */
  template &lt;class T&gt;
  T List&lt;T&gt;::next(){
      return list[nextIndex++];
  }
  
  /**
  * Check if the element is already in the list
  */
  template &lt;class T&gt;
  bool List&lt;T&gt;::contains( T &amp; element){
                                                          // Now, to check if the item already exists, we could just iterate over the array, but that gives us linear execution time.
                                                          // It seems sub-optimal to work in linear time here, when it feels like we shouldn't have to, but honestly, I'm too tired
                                                          // to care at this point.
      for(int i = 0; i &lt; (numberInList); i++){
          if(element != list[i])                          // We do this so that if the first item is not equal, we don't even bother checking the second condition.
          {
                                                          // The element isn't matched.  We have to finish iterating, though, before we can add it.
          }
          else{                                           // The element matched.  Return false.
              element = list[i];
              return true;
          }
      }
      return false;
  }
  
  /**
  * The implementation for this is very bad.  But, the requirements in the homework documentation are very restrictive.
  *
  * Ideally, we would have a companion class named Entry which kept the reference to the element via composition.
  *
  * Obviously, this is a list, so we only want unique entries.
  * 
  * if successful, we return a true.  Else, we're returning false.
  *
  */
  template&lt;class T&gt;
  bool List&lt;T&gt;::add( T &amp; element ){
      // If we've exceeded the loadFactor, we want to expand our array before we add.
      if( isAboveThreshold() ){
          int newSize = listSize*2;
          List&lt;T&gt; tempPtr = List&lt;T&gt;(newSize);
          for(int i = 0; i &lt; numberInList; i++){
              tempPtr.add(list[i]);
          }
  
          deepCopy(tempPtr);
      }
      if(!contains( element )){
          list[numberInList] = element;                   // if there are 4 in the list, the next empty index is 4, so this works.  We get our element, then post-increment.
          numberInList++;
          return true;
      }
      return false;
  
  }
  
  /**
  * Deep copy mechanism
  */
  template&lt;class T&gt;
  void List&lt;T&gt;::deepCopy(const List&lt;T&gt; &amp; toBeCopied){
  
      // Take care of shallow copying first.
      numberInList = toBeCopied.numberInList;
      listSize = toBeCopied.listSize;
      nextIndex = 0;                                      // We're getting a new list, so our iterator should start over.
  
                                                          // Now, to initialize the new list
      T *tempList = new T[listSize];
  
      for(int i = 0; i &lt; toBeCopied.numberInList; i++){
          // We can do this because we're in the List class.  We have access to private members.
          tempList[i] = toBeCopied.list[i];
      }
  
      delete [] list;
      list = tempList;
  
  
  
  }
  
  /**
  * boolean for if we've exceeded the loadFactor threshold.
  */
  template&lt;class T&gt;
  bool List&lt;T&gt;::isAboveThreshold(){
      if(numberInList != 0){
          double division = (double)numberInList/listSize;
          return (division &gt;= loadFactor)? true : false;
      }else
          return false;
  }
  
  /***
  *   Overloaded assignment operator
  */
  template &lt;class T&gt;
  List&lt;T&gt; &amp; List&lt;T&gt;::operator =( const List&lt;T&gt; &amp; assigner ){
      if(*this == &amp;assigner)
          return *this;
      delete[] list;
      deepCopy(assigner);
      return *this;
  }
  #endif
  </code></pre>
  
  <h2>Client.cpp</h2>
  
  <pre><code>#include "List.h"
  #include &lt;string&gt;
  #include&lt;iomanip&gt;
  #include &lt;iostream&gt;
  #include &lt;fstream&gt;
  #include &lt;stdlib.h&gt;
  using namespace std;
  
  struct Customer{
      int id;
      string name;
      string city;
      string address;
      float amount;
      Customer(){id=0; city="Default"; name="N/A"; address="N/A", amount = 0;}
      bool operator==( const Customer &amp; assign){
          if(assign.id == id)
              return true;
          else
              return false;
      }
      bool operator!=( const Customer &amp; assign){
          if(assign.id != id)
              return true;
          else
              return false;
      }
  };
  
  List&lt;Customer&gt; readCustomers();
  void printCustomers();
  
  int main(){
      cout.setf(std::ios::fixed);
      printCustomers();
      return 0;
  }
  
  // Definitions
  List&lt;Customer&gt; readCustomers(){
      List&lt;Customer&gt; WebsterCommunications(50);
      ifstream custFile;
      custFile.open("Customers.csv");
  
      // This could be abstracted out into another method, where we took the struct, a struct name, and the inFile, and spit back a 
      // customer from the file.  But, for now, we'll just settle with the code duplication.
      if(!custFile){
          cout &lt;&lt; "There was a problem reading the Customer File..." &lt;&lt; endl;
          exit(99);
      }
  
      while(!custFile.eof()){
          Customer tempCust;
          custFile&gt;&gt;tempCust.id;
          if(tempCust.id == 0)
              break;
          custFile.ignore();
          getline(custFile, tempCust.name, ',');
          getline(custFile, tempCust.address, ',');
          getline(custFile, tempCust.city, ',');
          custFile&gt;&gt;tempCust.amount;
          custFile.ignore();
          WebsterCommunications.add(tempCust);
      }
      custFile.close();
      return WebsterCommunications;
  }
  
  void printCustomers(){
              List&lt;Customer&gt; customers = readCustomers();
              double addCalc = 0.0;
  
              cout &lt;&lt; string( 100, '\n' );
              for(int i = 0; i &lt; customers.getSize(); i++){
                  Customer cust;
                  cust = customers.next();
                  cout &lt;&lt; "id: " &lt;&lt; cust.id &lt;&lt; " name: " &lt;&lt; cust.name &lt;&lt; " address: " &lt;&lt; cust.address &lt;&lt; " balance: " &lt;&lt; cust.amount &lt;&lt; endl;
                  addCalc += cust.amount;
              }
              cout.precision(2);
              cout &lt;&lt; "average: " &lt;&lt; (addCalc / customers.getSize()) &lt;&lt; endl;
              int isActive = 1;
              cout &lt;&lt; "Please enter a customer's id to find them (0 to exit):" &lt;&lt; endl;
              while(isActive){
                  cin &gt;&gt; isActive;
                  if(!isActive){
                      return;
                  }
                  Customer tempCust;
                  tempCust.id = isActive;
                  if(customers.contains(tempCust)){
                      cout &lt;&lt; "id: " &lt;&lt; tempCust.id &lt;&lt; " name: " &lt;&lt; tempCust.name &lt;&lt; " address: " &lt;&lt; tempCust.address &lt;&lt; " balance: " &lt;&lt; tempCust.amount &lt;&lt; endl;
                  }
                  else{
                      cout &lt;&lt; "That customer is not found" &lt;&lt; endl;
                  }
                  cout &lt;&lt; "Please enter a customer's id to find them (0 to exit):" &lt;&lt; endl;
              }
  }
  </code></pre>