views:

359

answers:

2

I'm new to C++ programming and would greatly appreciate replies that don't assume much prior knowledge.

Thanks to suggestions here, I've created an unordered map:

typedef std::tr1::unordered_map<std::string, Strain*> hmap;

The data in this map are pointers to instances of class Strain. As soon as these instances are created, I create pointers to them, and I then add these pointers to my hash table (hmap strainTable) and to another vector (vector< Strain *> liveStrains), e.g.,

string MRCA;
for ( int b = 0; b < SEQ_LENGTH; b++ ) {
 int randBase = rgen.uniform(0,NUM_BASES); 
 MRCA.push_back( BASES[ randBase ] );
}
Strain * firstStrainPtr;
firstStrainPtr = new Strain( idCtr, MRCA, NUM_STEPS );
liveStrains.push_back( firstStrainPtr ); 
strainTable[ MRCA ]= firstStrainPtr;

Instances of class Strain are never deleted, nor are pointers to them removed from strainTable. Pointers do occasionally move between vector< Strain * > liveStrains and vector< Strain * > deadStrains, but once on strainTable, they stay on strainTable.

Is this kosher? As long as the underlying instances are never destroyed, will the pointers added to them remain intact?

Is it also correct that I should always be able to get member attributes from the pointers in strainTable by using, e.g., for the first entry,

 hmap::const_iterator itr1 = strainTable.begin();
 int id = (itr1->second)->getStrainID();

I'm finding that after a while, pointers in my strainTable point to garbage.

+1  A: 

if you never delete them, then the pointers are still ok. On the other hand, you might want to keep things a bit tidier and use standard containers for the whole shebang.

typedef std::tr1::unordered_map<std::string, Strain> hmap;
typedef std::tr1::unordered_map<std::string, hmap::iterator> weakhmap;

hmap strainTable;
weakhmap liveStrains;
Strain firstStrain( idCtr, MRCA, NUM_STEPS );
strainTable[MRCA] = firstStrain;
liveStrains[MRCA] = strainTable.find(MRCA);
TokenMacGuy
Holy cow, that makes so much sense. I originally had vector< Strains > liveStrains (and same for deadStrains), and then I realized I needed this hash map, and so I switched to pointers for liveStrains--but keeping the Strain objects in the hash table is much better. Thanks also for showing the syntax.
Sarah
p.s. I need liveStrains to be a vector because I iterate over it many, many times in the simulation--I thought a vector would be faster than an unordered_map in this case.
Sarah
yes, of course a `std::vector<hmap::iterator>` will work just fine, if that's what you need instead.
TokenMacGuy
Actually, I'm a little concerned that if the table size changes, the pointers and iterators will become invalid... I think I'll stick to the unordered_map<std::string, Strain *> format.
Sarah
+1  A: 

A pointer to any object allocated with new will remain valid until you call delete on the object. You can copy the pointer as much as you like, and it will be valid as long as the underlying object has not been deleted.

Secondly, yes, you are correct that you can access object attributes from the stored pointers via container iterators. But always check to make sure that the return value of hmap::find() is not equal to hmap::end().

So what you describe is fine. Now, as to why the pointers in your strainTable are ending up pointing to garbage, I couldn't say without more details. Are you sure you're not deleting any objects anywhere? Are you sure that when you copy pointers from one vector to the other, you are doing it correctly?

Charles Salvia
Thanks. I hadn't realized it would be careful to check that hmap::find() != hmap::end(). I'm going to step through my code carefully later with the debugger to see where the weirdness starts. Since I don't call 'delete,' I'm pretty sure I'm not deleting anything, but my pointers could well be messed up. I'm going to restructure the hash table to have Strains for data (rather than Strain * ) and see if that helps first.
Sarah