Solved

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

Posted on 2000-03-23
5
180 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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
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 learn how to clear a vector as well as how to detect empty vectors in C++.

747 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now