First time using STL lists, need help/opinions

Started by
5 comments, last by BauerGL 21 years, 8 months ago
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

@mikaelbauer

Super Sportmatchen - A retro multiplayer competitive sports game project!

Advertisement
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 ]
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 CModelManagerCModelManager 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 oneCMD2Model *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]

@mikaelbauer

Super Sportmatchen - A retro multiplayer competitive sports game project!

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)]
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
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 ]
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.

char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/
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 oneCMD2Model *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]

This topic is closed to new replies.

Advertisement