tags:

views:

62

answers:

2

I have a std::vector< tr1::shared_ptr<mapObject> > that I'm trying build from data contained in a compressed file. Here's the function I'm attempting to do that with:

    using std::tr1::shared_ptr;

    template<typename T>
    void loadSharedPtrVector(std::vector< shared_ptr<T> >& vect, TCODZip& zip)
    // the TCODZip is the compression buffer I'm loading the data from.  It's
    // working correctly and isn't really part of this problem.
    {
        vect.clear();

        // load the size of the saved vector
        int numT = zip.getInt();

        // load the saved vector            
        for(int i=0; i<numT; ++i)
        {
            int type = zip.getInt();
            shared_ptr<T> Tptr(new T);
            T newT = T::loadType(type, zip);                
            Tptr.reset(&newT);
            std::cerr << "load: " << Tptr->getPosition() << std::endl; // outputs correct values
            vect.push_back(Tptr);
        }
        for(int i=0; i<numT; ++i)
        {
            // outputs the last value pushed onto vect
            std::cerr << "loadDone: " << vect[i]->getPosition() << std::endl;
        }
    }

The above function is called by this bit of code here:

        typedef std::tr1::shared_ptr<mapObject> featurePtr;

        // 'features' is a std::vector<featurePtr>, 'zip' is a TCODZip previously declared
        utility::loadSharedPtrVector<mapObject>(features, zip);

        vector<featurePtr>::const_iterator fit;
        for(fit=features.begin(); fit<features.end(); ++fit) 
        {
            // outputs mostly garbage
            cerr << "afterCall: " << (*fit)->getPosition() << endl;
        }

When this is run, the cerr statements give this output (each set of output has ~50 lines, so I cut out most for brevity):

load: (5,40)
load: (5,45)
load: (5,58)
(etc.  all 'load' lines are correct output)
load: (87,68)
load: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
(etc. all 'loadDone' lines are the same)
afterCall: (11,5)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
(etc. all 'afterCall' lines are the same except for the first)

I apparently have some misconceptions about how shared_ptrs work. I realized that I'm pushing copies of Tptr into vect, and that's why all of its indices are the same, although I thought that declaring a new shared_ptr in the loop would make a separate pointer from the other ones already in vect, but I guess not.

I have no idea why the 'afterCall' set of output is different from the 'loadDone' set (except for that first value). In addition to (10,1) it has also output (2274756,134747232) and (134747232, 16), although it outputs (10,1) more than any other.

I suspect that my problem boils down to my misuse of shared_ptr. Can anyone tell me exactly how I'm misusing it? The tutorials I find online haven't been very helpful in this regard.

+3  A: 
Nikolai N Fetissov
This fixed it. Thanks.
Max
A: 

I have spotted the same defect in your code as Nikolai did, and erased the shared_ptr which is useless:

template<typename T>
void loadSharedPtrVector(std::vector<T> & vect, TCODZip& zip)
// the TCODZip is the compression buffer I'm loading the data from.  It's
// working correctly and isn't really part of this problem.
{
    vect.clear();

    // load the size of the saved vector
    int numT = zip.getInt();

    // load the saved vector            
    for(int i=0; i<numT; ++i)
    {
        int type = zip.getInt();
        vect.push_back(T::loadType(type, zip));
    }
    for(int i=0; i<numT; ++i)
    {
        // outputs the last value pushed onto vect
        std::cerr << "loadDone: " << vect[i].getPosition() << std::endl;
    }
}
tojas
Without knowing something about the `mapObject` class, we can't say that the shared_ptr is useless. Maybe `mapObject` has no copy constructor, or maybe the copy constructor has poor performance.
JWWalker
`mapObject` is an abstract base class, and `features` is a vector containing objects derived from it. Since I can't instantiate `mapObject` directly, I need to have a pointer to it.
Max