C++ vector of class objects referencing external class

Started by
16 comments, last by Ubermeowmix 10 years, 10 months ago

However, this can only be achieved through pointers or references. Since you cannot store references in dynamic containers you need to work with pointers.


std::vector<CUnit *> units;
 
units.push_back(new CUnitA);
units.push_back(new CUnitB);
units.push_back(new CUnitC);
The three objects of the derived types has to be dynamically allocated. You are strongly advised to use smart pointers instead of raw pointers though, but which one to use depends on how the ownership of the object shall be handled.

Awesome i'll research smart pointers then.

So I can have a vector of groups, and within that vectors of units, does that massively affect memory usage?


Not saying anything about the design, but you certain can do that. Memory usage can mean different things though. Constant virtual dispatching if you're, say, iterating over the containers to call a virtual function on all units, may very well become a problem before the amount of memory used does. If you intend to use the type system to distinguish between similar units, then consider a data-driven approach instead. Do you really need the units to have different types instead of just having a single unit type with different data describing the type?

Plus I've been looking into save files and I wanted to clear up something there too as it links to the same issue.

When saving is it better to parse out all the variables in the classes and write them like XML (for example) and then populate in reverse when loading?

P.S. gotta go to work so it's going to be a late reply.

Serializing the data becomes a bigger problem if you, instead of using a data-driven approach with a single type, also have to determine the correct type within the language itself. Not only do you have to read the data from the external source, you also have to determine whether to call new on CUnitA, CUnitB or CUnitC on your data. Again, do you really need the different types?

Advertisement

Can anyone explain to me why the destructor is being called on the unit obects before I have called the delete unit function, I thought the pointer to new meant that they stayed in scope until the class obect group has been deleted from the vArmy vector?

Two questions:

1. how do I properly delete an object when it is created dynamically in a class (or is it culled when the class is deleted?).

2. Is a vector a pointer already, and if so when things are passed into it do they need to be zeroed out when being deleted?

class CGroup
{
public:
CGroup()
{
CUnit* pNewUnit = new CUnit(0, 5);
m_vTroups.push_back( *pNewUnit );
}
~CGroup() {}

void mfAddUnit(int type, int health)
{
std::cout << "Unit created!\n";
m_vTroups.push_back( CUnit( type, health) );
}

void mfDelUnit(size_t index)
{
m_vTroups.erase(m_vTroups.begin() + index);
}

std::vector<CUnit> mfRtnVector() const
{
return m_vTroups;
}

size_t size() const
{
return m_vTroups.size();
}
private:
std::vector<CUnit> m_vTroups;
int m_iNumber;
};

class CUnit
{
public:
CUnit()
{
m_iType = 0;
m_iHealth = 5;
}

CUnit(int iT, int iH)
{
std::cout << "CUnit type " << iT << ", health " << iH << " \n";
m_iType = iT;
m_iHealth = iH;
}
~CUnit() {}

void mfirSetInt(int iT, int iH) { m_iType = iT; m_iHealth = iH; }
void mfirGetInt(int& iT, int& iH) { iT = m_iType; iH = m_iHealth; }

private:
int m_iType;
int m_iHealth;
};

int main()

{

std::vector<CGroup> vArmy;

CGroup* pNewGroup = new CGroup;
vArmy.push_back( *pNewGroup );

//etc

}

If you get near a point, make it!

Don't allocate the items with new. For example, in main, you allocate a new CGroup object, and put a copy of it into the vArmy vector. The allocated object is then lost in void and you have a memory leak. The destructor being called is the destructor for the object in the vArmy vector.

int main()
{
    std::vector<CGroup> vArmy;

    vArmy.push_back( CGroup() );
 }

Sorry, I missed that you actually had two explicit questions.

Can anyone explain to me why the destructor is being called on the unit obects before I have called the delete unit function, I thought the pointer to new meant that they stayed in scope until the class obect group has been deleted from the vArmy vector?

Two questions:

1. how do I properly delete an object when it is created dynamically in a class (or is it culled when the class is deleted?).

delete what you new, but when working with values, like std::vector<CGroup> instead of std::vector<CGroup *>, you don't have to new anything so there's nothing to delete either.

2. Is a vector a pointer already, and if so when things are passed into it do they need to be zeroed out when being deleted?

A vector stores values of the type you specify. If you ask it to store instances of CGroup, that is std::vector<CGroup>, then no pointers are stored, only values and copies of CGroup instances.

Note that if you have a C++11 compiler, you can use emplace_back() instead of push_back(), which constructs the object in place with the arguments you supply without needing to make a copy. So instead of
m_vTroups.push_back( CUnit( type, health) );
You can have
m_vTroups.emplace_back(type, health);

2. Is a vector a pointer already, and if so when things are passed into it do they need to be zeroed out when being deleted?

A vector stores values of the type you specify. If you ask it to store instances of CGroup, that is std::vector<CGroup>, then no pointers are stored, only values and copies of CGroup instances.

This is the part i'm having trouble with, when in the class object CGroup and loading the CUnit on the fly into the vector within CGroup, the destructor of CUnit is called if I use a pointer or not. Why does it do this, is the vector being deleted or the CUnit being deleted?

Or is the complier calling the destructor everytime I read the objects of the vector?

If you get near a point, make it!

Every time you use push_back() to put something in a vector, the vector makes a copy of the object you pass it. If you pass push_back() a temporary object, the vector will make a copy of the temporary and then the compiler will destroy the temporary. It's also possible that they way you're reading from the vector is also generating extra temporary objects.

How are you tracking your CUnit destruction? It's entirely possible that you aren't seeing matching construction and destruction counts because you aren't tracking copy constructor calls.

How are you tracking your CUnit destruction? It's entirely possible that you aren't seeing matching construction and destruction counts because you aren't tracking copy constructor calls.

I just put a cout << "destructor called in CUnit\n"; in the destructor, so is this just the compiler making a copy of the object in the vector to read it temporarily? I've taken the pointer out of:

CUnit* pNewUnit = new CUnit(0, 5);
m_vTroups.push_back( *pNewUnit );

As you said I don't really need it with the vector. I am using a custom copy constructor:

CUnit(int iT, int iH)
{
std::cout << "CUnit COPY constructor called\n";
m_iType = iT;
m_iHealth = iH;
}

But as i've been reading through it looks apparent that I don't need to use referencing unless there are member pointers in the class!

If you get near a point, make it!

This topic is closed to new replies.

Advertisement