简体   繁体   中英

C++ Am I adding and accessing my Vector correctly?

I am creating an object and adding it to a std::vector and then later on accessing the std::vector to use member variables from the objects I place in it.

.h that contains the std::vector

std::vector<Field *> vFields;
inline std::vector<Field *> getFields() { return vFields; };

In the .cpp I do this:

Field* f1 = Field::createWithLocation(ccp( p.x, p.y));
addChild(f1->getFieldSprite(), 2);
getFields().push_back(f1); // add the new field to a container
//vFields.push_back(f1); // add the new field to a container

std::cout << "add - # of Fields: " << getFields().size() << std::endl;

When instantiating the Field* f1 above this is happening:

Field* Field::createWithLocation(cocos2d::CCPoint p)
{
    Field* f = new Field();
    //f->autorelease();
    f->initWithLocation(p);
    return f;
}

void Field::initWithLocation(cocos2d::CCPoint p)
{
    setFieldCenterPoint(p);
    setFieldGraphicName(FIELD::fieldIconFileName);

    setFieldSprite(cocos2d::CCSprite::create(getFieldGraphicName().c_str()));
     getFieldSprite()->setPosition(ccp(getFieldCenterPoint().x, getFieldCenterPoint().y));

    setFieldSize(getFieldSprite()->getContentSize());

    setFieldNumber(7159);

    setFieldTag(7159);

    std::cout << "When Field Created #: " << getFieldTag() << std::endl;
}

This works fine and when the Field object is created the std::vector says 1 in size() and the getFieldTag() returns 7159 like it was set.

The problem is when I go to access the Field from the vector something happens and I crash. I found that if I output getTagNumber() it is way different.

Example of accessing the vector:

else if (getFieldLayerState() == kActive)
{
    // so did they click on a field?
    std::cout << "Field Layer Status Is Active" << std::endl;
    std::cout << "touch - # of Fields: " << vFields.size() << std::endl;

    // Loop through the field vector and get the size of each field and see if it was tapped    
    for (int f=0; f<vFields.size(); f++)
    {
        //field = (Field*) getFields().at(f);
        Field* field = (Field*) vFields.at(f);

        std::cout << "field #: "<< field->getFieldNumber() << std::endl;
        std::cout << "field tag: "<< field->getFieldTag() << std::endl;

        if (field->getFieldSprite()->boundingBox().containsPoint(location))
        {
            std::cout << "touched field #: "<< field->getFieldNumber() << std::endl;
            std::cout << "touched field tag: "<< field->getFieldTag() << std::endl;
            _dir->Instance()->getAudioEngine()->playBackgroundMusic("tap.mp3", false);    
        }
     }
}

Sample Output from the cout statements:

When Field Created #: 7159
add - # of Fields: 1
Field Layer Status Is Active

touch - # of Fields: 1
field #: 1769234804
field tag: 353394533`

I crash at the if (field->getFieldSprite()->boundingBox().containsPoint(location)) line above with an EXEC_BAD_ACCESS and it is clear that what is in the vector has changed from what I put in it, or so it seems.

Can anyone help me understand what I am doing wrong?

Your getFields function returns a copy of the vector. So any changes to the returned vector will only happen in the copy, and not the original.

You want to return a reference .

std::vector<Field*>& getFields() { return vFields; }
//                 ^
// Note the ampersand

You might also want to add a const overload of the function as well:

const std::vector<Field*>& getFields() const { return vFields; }
// ^                                      ^
// Note the two `const` modifiers, the last one is important

Then if you modify the vector, eg by adding to it, the compiler will select the first non-const overload. And if you don't modify the vector, eg when you just call size on the vector, the compiler will select the second const overload.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM