Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 194
  • Last Modified:

How can I create a list entry without wasting memory?

//  This code produces two "Contigs" and I only want one.  
// This can be found at:  http://waldo.wi.mit.edu/~kstanley/STL/ex1.cc
#include <list>

class Contig {
 public:
  char *id; // This is just for debug

  Contig( );
  Contig( char* name) ;
  ~Contig( );
};

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

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

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

typedef  list<Contig>::iterator Contig_itr;

main(){

  list<Contig> AllContigs;

  AllContigs.push_front( Contig("what") ) ;  //  THE PROBLEM IS: This appears to create two "Contigs", not just one  
  Contig_itr a = (AllContigs.begin()) ;
  a->id = "A";
 
}

0
klopter
Asked:
klopter
  • 4
  • 2
1 Solution
 
nietodCommented:
>> AllContigs.push_front( Contig("what") ) ;  //  
>> THE PROBLEM IS: This appears to create
>> two "Contigs", not just one  
This is not a PROBLEM, but it might be a problem.  i.e the code works correctly, but might not be what you expected.  

It does create two Contigs.  One contig is the one you want, the one that gets stored in AllContigs.   The other contig is a "unnamed temporary".  This is an object created by the compiler and destroyed at the end of the statement.   These unamed temporaries can occur for a variety of reasons in a variety of circumstances, in this case you are forcing the compiler to create it by invoking a constructor, like in

   Contig("what");

this statement creates a contig object (but not a named varaible) and then destroys it.

So you see that two objects are getting created, but one is destroyed almost immediately.

continues.
0
 
nietodCommented:
So the net result should be what you want.  i.e after the statement is executed there is only one object, the one in the list<>.  but the code is a little innefficient.  There are three operations that appear to not be needed, the creation of the temporary, the copying of the remporary to the list, and the destruction of the temporary.  This is one of the weaknesses of working with generic containers, especially the STL containers.  However if the class is relatively small and simple these three operations are probably pretty trivial and can be ignored.  If that is not the case, there sometimes are other things that can be done, like using reference counting to allow the object to be copied into the list without an actual copy being made.
0
 
nietodCommented:
Another way around this is to have the container store pointers to dynamcially allocated object, then there is no need to copy items in to the container, but the problem with this is that it is easy to have memory leaks, and the main reason for using these containers is to avoid those memory leaks, so I don't really recommend it.

I guess I would first consider if this extra temproary is really all that costly.  If not, live with it, most poeple do.  If it is too costly, consider using reference counting to make the class more efficient.  That will probably have benefits in other cicumstances too.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
klopterAuthor Commented:
This is not likely to be a performance
critical section of code.  I was more
concerned about the apparent waste of
memory.  I won't pretend that I
like the creation, copy, delete aspect,
but it isn't a showstopper.  I know
that I can get rid of the cration and
deletion by going back to having a
temporary and it seems likely that
a good optimizing compiler could get
rid of all three.  (It can't in this
case because of my debug cout
statements).

Anyway, as long as you say that this
is the right semantics, I'll stick with
these for now.

Now, on the the erase problem.
More on that later.

Ken

0
 
klopterAuthor Commented:
I agree that the extra copies probably won't be a
significant perofrmance issue. I am not 100% positive
because basically this code is a graph manipulation
code, so I could imagine it is being an
issue.  But, though I don't immediately see
how to use reference counting to make this more
efficient, I take your word for it and will
cross that bridge if/when I come to it.

Thanks again,
  Ken
0
 
nietodCommented:
>> I know that I can get rid of the cration and
>> deletion by going back to having a
>> temporary
You can't get rid of it, but you can use 2 named temporary object to initialize many entries in the list, so yoiyu have only one extra construction and destruction, you still have lots of extra copies.


>>  and it seems likely that
>> a good optimizing compiler could get
>> rid of all three.  
Very unlikely.  It has to be able to determine that there will be no side effects from doing so and that is nearly impossible to do.  Any of these funtions could have nexpected side effects, like you might set the current screen color from them.  There are rules governing when the compiler can optimize away a temporaries and copy construction, but I can't remember them off-hand.  the rules are very restrictive.

>> But, though I don't immediately see
>> how to use reference counting to make this more
>> efficient,
whenever an object is slow to copy, reference counting can be used to make the copying nearly trivial.  If the objects will store lots of data, like large lists of other objects, they can be slow to copy.  If you reference count the class, you never need to copy it, you just copy a smart pointer class, which is fast to copy.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now