Archived

This topic is now archived and is closed to further replies.

BauerGL

First time using STL lists, need help/opinions

Recommended Posts

Hi, I''m doing a ModelManager class which should make sure I''m only loading my models once etc. Right now I have a STL list which traverses each model, looks if it has been loaded before, and takes appropriate action. But I''m kinda lost in the STL woods and I''m unsure how to go on about deleting objects from the list etc. My loading/insertion function is probably wrong too. I have searched the forums and Google but haven''t been able to find anything that can help me (or that I could understand), so no I''m turning to you. This is my CModelManager and CModelHolder classes, in a .h and a .cpp file:
  
#ifndef CMODELMANAGER_H_
#define CMODELMANAGER_H_

#include <list>
#include "CModel.h"
using namespace std;

class CModelHolder
{
public:
	CModelHolder(void); 
	CModelHolder(const CModelHolder ©);
	~CModelHolder(void);

	char *m_strFileName;
	CMD2Model m_Model;
	int count;													// Holds the count the model has been assigned

};

class CModelManager
{
public:
	CModelManager(void);
	~CModelManager(void);

	CMD2Model *GetModel(char *modelFilename, char *modelTexture);
	bool ReleaseModel(char *modelFilename);

    list<CModelHolder> m_ModelList;
	list<CModelHolder>::iterator m_Iterator;
};

extern CModelManager g_ModelManager;

#endif
  

  
#include "CModelManager.h"

// Global CModelManager

CModelManager g_ModelManager;

CModelHolder::CModelHolder(void)
{
	m_strFileName = NULL;
	count = 0;
}

CModelHolder::CModelHolder(const CModelHolder ©)
{
	m_strFileName = copy.m_strFileName;
	count = copy.count;
	m_Model = copy.m_Model;
}

CModelHolder::~CModelHolder(void)
{
}

CModelManager::CModelManager(void)
{
	m_ModelList.clear();
}

CModelManager::~CModelManager(void)
{
}

// Compares 2 model filenames and if they match it returns the model, else it loads in a new one

CMD2Model *CModelManager::GetModel(char *modelFilename, char *modelTexture)
{
	for(m_Iterator = m_ModelList.begin(); m_Iterator != m_ModelList.end(); m_Iterator++)
	{
		if(!strcmp(m_Iterator->m_strFileName, modelFilename))
		{
			m_Iterator->count++;
			return &(m_Iterator->m_Model);
		}
	}

	CModelHolder *newModel = new CModelHolder;
	if(newModel->m_Model.LoadModelAndSkin(modelFilename, modelTexture))
	{
		newModel->count = 1;
		newModel->m_strFileName = modelFilename;

		m_ModelList.push_back(*newModel);

		return &(newModel->m_Model);
	}
	else
		return NULL;
}

bool CModelManager::ReleaseModel(char *modelFilename)
{
	for(m_Iterator = m_ModelList.begin(); m_Iterator != m_ModelList.end(); m_Iterator++)
	{
		if(!strcmp(m_Iterator->m_strFileName, modelFilename))
		{
			m_Iterator->count--;

			if(m_Iterator->count <= 0)
			{
				m_Iterator->m_Model.UnloadModel();

				delete &(m_Iterator);
				m_ModelList.erase(m_Iterator++);
			}

			return true;
		}
	}

	return false;
}
  
What I want this to do is: Store a list of objects which consists of a filename (the path to the model), the count of how many times the model has been assigned, and the model itself. Then in the GetModel() function I search the list to see if I have already loaded a model with the filename given as the function parameter. If I have, I return a pointer to that model. If I haven''t, I load in the model, assign the filename etc, and pushes the object on the list. The ReleaseModel() function should work in the same way but opposite. When the count is 0 (i.e when no object is using it anymore) it unloads the model, and deletes the memory held by the modelHolder, and removes the object from the list. The problem is that I''m getting a "Debug Assertion Failed" error when running the program in Debug mode, but not in Release mode. The error comes up when I''m closing the application (i.e when I''m unloading the model). The model loads and renders fine. Thanks alot for helping, and remember that I''m a total newbie about STL so be kind

Share this post


Link to post
Share on other sites
Ack. Don''t delete the iterators themselves unless you allocated them with new. Let them go out of scope normally. Lines like "delete &(m_Iterator);" will be doing the damage. Also, what''s the point of "m_Iterator++" when the next line is a return? Don''t waste time incrementing something when you''re destroying it on the next line.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
Hmm yea that's what I'm trying to tell you, I'm a _complete_ newbie with STL (but I do grasp "normal" pointers pretty well). My implementation is a very very shattered one with bits coming from old forum posts, some tips from irc, the STL table of contents etc... Have you got any better place to learn from? or could you give me an example or two?


I've got it explained to me that I should use a vector instead... so I rewrote it using vectors instead, but I now I get an access violation in the GetModel() function. This is the new code:


  
#ifndef CMODELMANAGER_H_
#define CMODELMANAGER_H_

#include <vector>
#include "CModel.h"
using namespace std;

class CModelHolder
{
public:
CModelHolder(void);
CModelHolder(const CModelHolder ©);
~CModelHolder(void);

char *m_strFileName;
CMD2Model m_Model;
int m_Count; // Holds the count the model has been assigned

};

class CModelManager
{
public:
CModelManager(void);
~CModelManager(void);

CMD2Model *GetModel(char *modelFilename, char *modelTexture);
bool ReleaseModel(char *modelFilename);

vector<CModelHolder> m_ModelVector;
};

extern CModelManager g_ModelManager;

#endif



  
#include "CModelManager.h"

// Global CModelManager

CModelManager g_ModelManager;

CModelHolder::CModelHolder(void)
{
m_strFileName = NULL;
m_Count = 0;
}

CModelHolder::CModelHolder(const CModelHolder ©)
{
m_strFileName = copy.m_strFileName;
m_Count = copy.m_Count;
m_Model = copy.m_Model;
}

CModelHolder::~CModelHolder(void)
{
}

CModelManager::CModelManager(void)
{
m_ModelVector.clear();
}

CModelManager::~CModelManager(void)
{
}

// Compares 2 model filenames and if they match it returns a pointer to the model, else it loads in a new one

CMD2Model *CModelManager::GetModel(char *modelFilename, char *modelTexture)
{
for(int i = 0; i < m_ModelVector.size(); i++)
{
if(!strcmp(m_ModelVector[i].m_strFileName, modelFilename))
{
m_ModelVector[i].m_Count++;
return &(m_ModelVector[i].m_Model);
}
}

// We didn't find the model so load it in

CModelHolder newModel;
if(newModel.m_Model.LoadModelAndSkin(modelFilename, modelTexture))
{
newModel.m_Count = 1;
newModel.m_strFileName = modelFilename;
m_ModelVector.push_back(newModel);

return &(newModel.m_Model);
}
else
return NULL;
}

bool CModelManager::ReleaseModel(char *modelFilename)
{
for(int i = 0; i < m_ModelVector.size(); i++)
{
if(!strcmp(m_ModelVector[i].m_strFileName, modelFilename))
{
m_ModelVector[i].m_Count--;

if(m_ModelVector[i].m_Count <= 0)
{
m_ModelVector[i].m_strFileName = 0;
m_ModelVector[i].m_Count = 0;
m_ModelVector[i].m_Model.UnloadModel();

CModelHolder temp;
temp = m_ModelVector[i];
m_ModelVector[i] = m_ModelVector.back();
m_ModelVector.back() = temp;

m_ModelVector.pop_back();
}

return true;
}
}


return false;
}


Sorry for posting such newbie questions or for "abusing" the source tags, but I'm totally lost in this. Thanks for your time.



[edited by - BauerGL on August 17, 2002 4:03:41 PM]

Share this post


Link to post
Share on other sites
There are simple examples of using the STL in the MSVC help and probably on the STLport site as well.

Also, A google search turned up several promising links.

The STL is composed of several concepts :
Containers
Iterators
Algorithms

Algorithms transverse containers using iterators.


"Effective STL" by Scott Meyers is a pretty good book to get you started using the STL.

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

[Look for information | GDNet Start Here | GDNet Search Tool | GDNet FAQ | MSDN RTF[L] | SGI STL Docs | STFW | Asking Smart Questions ]

[Free C++ Libraries | Boost | ACE | Loki | MTL | Blitz++ | wxWindows| Spirit(xBNF)]

Share this post


Link to post
Share on other sites
Why don''t you find the exact line the error is on? If it''ll give you the function, it''ll give you the line. And I wouldn''t have recommended switching to a vector at this stage, but I guess it doesn''t do any harm.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
quote:
"Effective STL" by Scott Meyers is a pretty good book to get you started using the STL.

I agree that it is a pretty good book, but it is neither suitable for, nor intended for, complete STL virgins. It''s a bunch of tips for improving your STL experience, not a tutorial for the beginner.

Share this post


Link to post
Share on other sites
I'd recommend "The C++ Standard Library A Tutorial and Reference". Also if you are storing your models in a contain and are wanting to find them by name then you might want to look at using a std::map instead of a vector, or have a vector and a map.
Your map would be declared like this:

          
std::map<std::string,CMD2Model * > modelRegistry;


Your getModel method can then be done like this:


              
// Compares 2 model filenames and if they match it returns the model, else it loads in a new one

CMD2Model *CModelManager::GetModel(std::string modelFilename,std::string modelTexture)
{
//get an iterator for our model map

std::map<std::string,CMD2Model * >::iterator modelIt = modelRegistry.find(modelFileName);

if(modelIt != modelRegistry.end())
{//we found the model.

return (modelIt->second);
}
else
{//didn't find it. So load it

CModelHolder *newModel = new CModelHolder;
if(newModel->m_Model.LoadModelAndSkin(modelFilename,modelTexture))
{
newModel->count = 1;
newModel->m_strFileName = modelFilename;
modelRegistry[modelFileName] = newModel;
return newModel;
}
else
return NULL;
}
}




[edited by - bslayerw on August 18, 2002 4:27:45 PM]

[edited by - bslayerw on August 18, 2002 4:28:45 PM]

Share this post


Link to post
Share on other sites