[TriLUG] c++ proper away do an assignment overload for a linked list.

Ralph Blach chipperb at nc.rr.com
Thu Jan 28 14:30:11 EST 2010


To learn C++ an am trying to write a linked list, no hard, in c++,

However, creating an proper assignment overload, is very difficult.

Here is my code so far.
#include <iostream>
#include <cstdlib>

using namespace std;

class ll_node
{
     public :
     ll_node() {next = 0;prev = 0; }
     ll_node(const string &val) {next = 0; prev=0; value=val;}
     ll_node(ll_node * n_ll_node,const string & 
val){next=n_ll_node;prev=0;value=val;}
     int get_s() ;
     void set_s( int x);


     //  work with the next porinters
     void     set_next(  ll_node * lln_next) {next=lln_next;};
     ll_node *get_next (void) const  {return next;}
     const ll_node *const get_next ( ll_node*  lnode  )  {return 
lnode->get_next();}

     // previous pointe
     void     set_prev( ll_node * lln_prev){prev=lln_prev;};
     ll_node * get_prev( ) const                              {return 
prev;};
     const ll_node * const get_prev  ( ll_node*  lnode  ) const    
{return lnode->get_prev();}


     //data operators
     void set_value(const  int & s){ value=s;}
     string   get_value  () const {return value;}
     void set_st(int i){s=i;}
     int get_st(int i){return s;}

     //
     // private area for the linked list
     private:
      string value;
      ll_node *next;
      ll_node *prev;
     static int s;
};


class ll_list
{
   public:
   void push_top(const string &i);
   string pop_top(void);
   void  walk_top(void);
   void  walk_bottom(void);
   const ll_node *    get_first   ( ) const  {return first;}
   const ll_node *   get_last    ( ) const  {return last;}
   void push_bottom(const string &value);
   string pop_bottom(void);
   //clear the list delete all values.
   void   clear(void);

    //see if the list if empty, or how many elements are in the list
   bool   empty(void)const { if (llsize) return false; else return true;  }
   int   length (void)const   {return llsize;}
   //find a value
   ll_node  *  find_value(const string &val);
   //constructors
   ll_list () {first=0;last=0;next=0;llsize=0;}
   //destructor
   ~ll_list() {clear ();};
   static const int llempty=-1>>1;   //the largest int is alwasy a 
return code

   // the assignemt overload
   ll_list & operator=(const ll_list &rhs);
   // the copy constructor
   ll_list ( const ll_list & list );
   //friend const ll_list operator +(const ll_lhs &lhs, const ll_node &rhs);


   private:
   int llsize;
   ll_node * first;
   ll_node * last;
   ll_node * next;

};
#if 0
//copy constuctor.
ll_list::ll_list(const ll_list & list )
{
     const ll_node * const  lnode  =list.get_last();
     ll_node * tmp=lnode;
     string s;
     first=0;//one has to initialize all the values.
     last=0; //of the new list
     llsize=0;


         while (tmp  )
         {
             s=tmp->get_value();
             push_top(s);
             tmp=tmp->get_prev();
         }
}
#endif
/******************************************************/
// = assignement overload.
ll_list& ll_list::operator=(const ll_list &rhs) //<-here is the problem. 
I have to pass the rhs as a const &
{
     // Only do assignment if RHS is a different object from this.
     if (this != &rhs  )
     {
         if (rhs.empty())
         {
             clear();
             return *this;
         }

        string s;
        const  ll_node * const  lnode  =rhs.get_last();  //then recreate 
a read only node.  How do I create a read only or const node, that does not
                                                                                      //seem to mutate the right hand side, and does not have any back doors.

       //ll_node * tmp=lnode;
       // Deallocate, allocate new space, copy values...

            //first delete all the nodes
         clear();
             //next set the top of the rhs
             //next put all the nodes back on the new list.
         while (lnode  )
       {
             push_top(lnode->get_value());
             //cout<<"in assingmet lnode="<<lnode<<endl;
             lnode=lnode->get_prev(lnode);
         }

     }

     return *this;

}

void ll_list::push_top(const string &value)
{
     llsize++;
     //ll_node *tmp;
     first=new ll_node(first,value);
    if (last == 0 )  //start of the list no nodes in list
    {
        last = first;
    }
    else //it is not the first link we need to update the previous nodee
    {

         ll_node * next;
         next=first->get_next(); //so now we have the pointer to next,
                                 //link in the list.
         next->set_prev(first);
    }


}
string ll_list::pop_top(void)
{
     string value="";
     ll_node * tmp=0;
     if (first == 0 )
     {
         return "";
     }
     llsize--;
     tmp=first;
     if (first == last)
     {
         first=0;
         last=0;
         value=tmp->get_value();
     }
     else
     {
         first=first->get_next();
         first->set_prev(0);
     }
     value=tmp->get_value();
     delete tmp;
     return value;
}
//clear the link list.
void ll_list::clear(void)
{

     while ( first != 0 )
     {
         pop_top();
     }

}
//
void ll_list::walk_top(void)
{
     ll_node * nptr=first;
     while ( nptr)
     {

         cout<<nptr->get_value()<<endl;
         nptr=nptr->get_next();
     }
}
void ll_list::walk_bottom(void)
{
     ll_node * nptr=last;
     while ( nptr)
     {

         cout<<nptr->get_value()<<endl;
                 nptr=nptr->get_prev();

     }
}
ll_node * ll_list::find_value(const string & val)
{
     ll_node * nptr=first;
     while ( nptr)
     {
         if (val==nptr->get_value())
         {
             return nptr;
         }
         nptr=nptr->get_next();
     }
     return nptr;
}


void ll_list::push_bottom(const string &value)
{
    ll_node *tmp;
    llsize++;
    tmp=new ll_node(value);
    //now add the node to the bottome of thelist
    if (last == 0 )  //start of the list no nodes in list
    {
        last=first=tmp;
        tmp->set_prev(0);
        tmp->set_next(0);
    }
    else //it is not the first link we need to update the previous nodee
    {
         last->set_next(tmp);
         tmp->set_prev(last);
         last=tmp;
    }


}
string ll_list::pop_bottom(void)
{
     string value="";
     ll_node * tmp=0;
     if (first == 0 )
     {
         cout<<"list is empty"<<endl;
         return "";
     }
     llsize--;
     tmp=last;
     if (first == last)
     {
         first=0;
         last=0;
         value=tmp->get_value();
     }
     else
     {
         last=tmp->get_prev();
         last->set_next(0);
     }
     value=tmp->get_value();
     delete tmp;
     return value;
}
void copy_test( ll_list my_list)
{
     cout<<"in copy constructor test"<<endl;
     my_list.walk_top();


}
int main ( int argc, char * argv[])
{
     ll_list myll;
     ll_node  * lnode;
     string temp;
        myll.push_bottom("11");
     myll.push_bottom("12");
     myll.push_bottom("13");
     myll.push_bottom("14");
     cout<<"walk_top"<<endl;
     myll.walk_top();
     myll.pop_bottom();
     {
         cout <<"to destructor test"<<endl;
         ll_list newll;
         newll.push_top("aaa");
         newll.push_top("bbb");
         cout<<"newll walk top"<<endl<<endl;
         newll.walk_top();
         cout<<"myll walk top"<<endl<<endl;
         myll.walk_top();
         cout<<"to assingment\n\n"<<endl<<endl;
         newll=myll;
         cout<<"after assignemnt new walk top"<<endl<<endl;
         newll.walk_top();
         cout <<"to copy constructor"<< endl;
         copy_test(newll);
     }


   return 0;

}






More information about the TriLUG mailing list