Solved

Why can't I assign a pointer to the beginning of an STL list?

Posted on 2000-03-23
5
183 Views
Last Modified: 2010-04-02
#include <list>

class Contig {int q;};  // The shortest class I could make

main(){

  list<Contig> AllContigs;  

  Contig whatever;   // Just something that I can push onto the list

  AllContigs.push_front( whatever ) ;

  Contig *a = (AllContigs.begin()) ; // Why doesn't this work?
  Contig &b = *(AllContigs.begin()) ; //This does work.
}



I guess that I am going to have to use the & operator
(is it called a reference operator?).  In the greater
scheme of things this is undoubtably good.
Nonetheless, to me pointers and lists go hand-in-hand
and I don't understand why I can march through the
list with pointers like I would in C.

Thanks,
  Ken


0
Comment
Question by:klopter
  • 4
5 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 100 total points
ID: 2649625
list::begin() returns an iterator to an item in the list.   This is LIKE a pointer, but it is not a pointer (it is a class).

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 2649673
#include <list>

class Contig {int q;};  // The shortest class I could make

main(){

   list<Contig> AllContigs;  

   Contig whatever;   // Just something that I can push onto the list

   AllContigs.push_front( whatever ) ;

   list<Contig>::iterator a = (AllContigs.begin()) ;
}

Those list<Contig>::iterator's can get long an painful to type, so you may want to use typedef's to "shorten" them like

typedef  list<Contig>>::iterator Congig_itr;

   lContig_itr a = (AllContigs.begin()) ;

I guess I sort of missed the main question--why does the line

Contig &b = *(AllContigs.begin());

work?  This is because the iterator class that is returned by begin() overloads operator * so that operator * returns the item that the iterator refers to.   As you can see, by overloading ovperator * it makes the iterator seem like a pointer.  This is no accident.  The iterator works  like both a pointer in its function, and in the way that it is used (operator * and -> can "dereference" it, for some types of interators you can use + and - to get iterators to other items in the container, you like pointers.).   The reason this is done is that the STL defines many template algorithms that can be made to work with both pointers or iterators.  Thus you can use a sort algorithm to sort an array using pointers or to sort a vector<> using iterators.  All with the exact same template code.

Let me knw if you have any questions.
0
 

Author Comment

by:klopter
ID: 2650040
So, I take it that the right thing to
do is to use iterators.  

I am worried that my code is going to
become unreadable to my non-STL
compatible fellow workers, but I
will continue for now.

Here is what I am trying to create:
A list of items that I call contigs.
Each contig may have an arbitrary
number (typically 2) of neighbors to
the left, and an arbitrary
number of neighbors to
the right.  This graph of contigs
is symmetric in that if b is a's
neighbor to the left, a is b's neighbor
to the right.

I want the contigs to be a list rather
than a vector because I want to
be able to add and delete contigs.

I have a class named Contig which seems
to give me close to what I want.
But, on the other hand I may be a long
way off.

here is the code.  It is also at:
http://waldo.wi.mit.edu/~kstanley/STL/ex.cc

My current struggle is in getting the
last line to compile.  (Making sure
that b is a's neighbor to the left.)

Thanks,
  Ken

#include <list>
#include <assert.h>
#include <string>

class Contig {

 public:
  list<Contig*> left;
  list<Contig*> right;
  char *id; // This is just for debug

  void AddLeft( Contig &c ) ;
  void RemoveLeft( Contig &c ) ;

  Contig( );
  ~Contig( );

};

Contig::Contig() {
  id = (char *) NULL ;
}

Contig::~Contig() {
  if ( id ) cerr << " id = " << id << endl ;
  cerr << " Here we are in ~Contig" << endl ;
}

void Contig::AddLeft(  Contig &c ) {  // I started with Contig *c as the argument here, but &c seems to work better

  left.push_front( &c ) ;
  c.right.push_front( this ) ;
}

void Contig::RemoveLeft(  Contig &c ) {

  left.remove( &c ) ;
  c.right.remove( this ) ;
}

typedef  list<Contig>::iterator Contig_itr;

main(){

  list<Contig> AllContigs;

  Contig whatever;  // I don't really want this Contig, but I need something
  // to pass to  AllContigs.push_front
  whatever.id = "whatever";   // This belongs in a constructor, but id is only for debug anyway.

  AllContigs.push_front( whatever ) ;
  Contig_itr a = (AllContigs.begin()) ;
  a->id = "A";
 
  AllContigs.push_front( whatever ) ;
  Contig_itr b = (AllContigs.begin()) ;
  b->id = "B";

  a->AddLeft(*b);  // This should set a.left = b and b.right = a

  assert( a == b ) ;
  assert( *(a->left.begin()) == b ) ;   // I can't get this to work.
}

0
 
LVL 22

Expert Comment

by:nietod
ID: 2650100
>> I am worried that my code is going to
>> become unreadable to my non-STL
>> compatible fellow workers, but I
>> will continue for now
I'd be worried that it will be unreadable to me.

Using STL is definitely a change, but its not that big a change.  You might be feelign a bit overwhelmed af first, but that will pass quicky.  its probably a bit like the first time you programmed in C++ instead of C (assuming you made the switch) and saw all those weird ::'s and <>'s etc.

>> I want the contigs to be a list rather
>> than a vector because I want to
>> be able to add and delete contigs.
You can add and delete to both.  But if you will be doing lots of adding and deleting, the a list will be more efficient.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 2650169
>>  Contig whatever;  // I don't really want this Contig, but I need something
>>                // to pass to  AllContigs.push_front

ideally, you would add a constructor to Contig, either a default constructor, or one that specifies values for the data embers you need to have set, like ID, so then instead of

                AllContigs.push_front( whatever ) ;
                Contig_itr a = (AllContigs.begin()) ;
                a->id = "A";

you can do.

                AllContigs.push_front(Contigs("A") ) ;

simpler?

>>  assert( a == b ) ;

But this is not true.  a is now the 2nd item because b is the new first item.

>> assert( *(a->left.begin()) == b ) ;   // I can't get this to work.
These aren't equal either.  Does this compile?
b is an iterator of type list<Config>::iterator.  the a->left.begin() returns an iterator of type list<Config *>::iterator.  then you do an * on this so you get a Config* on the left.  

You want to see if the two are at the same address, so you could do

assert( *(a->left.begin()) == &(*b))

nice huh?  Actually this ugliness has nothing to do with STL.  If you did the same thing with pointers and linked lists you would have the exact same issues and code.
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question