STL vector problem in my texture mgr.

Started by
4 comments, last by Programmer16 19 years, 10 months ago
Hey, I''m having a problem with my texture manager. Here''s the code I have:
class EgTextureManager
{
	vector<EgTexture*> m_vTextures;
	int m_iTextureCount;
	IDirect3DDevice9* m_pDevice;

public:
	EgTextureManager(int iTexCount = 0);
	~EgTextureManager();
	void SetDevice(IDirect3DDevice9* pDevice);
	EgTexture* CreateTexture(char* pFilename, D3DCOLOR clrColorKey = EG_ARGB(0, 255, 0, 255));
	EgTexture* GetTexture(char* pFilename);
};

EgTextureManager::EgTextureManager(int iTexCount)
{
	m_iTextureCount = iTexCount;
}

EgTextureManager::~EgTextureManager()
{
	EgTexture* pTemp = NULL;
	vector<EgTexture*>::iterator vItor;
	for(vItor = m_vTextures.begin(); vItor != m_vTextures.end(); vItor++)
	{
		pTemp = *vItor;
		m_vTextures.erase(vItor);
		delete pTemp;
	}
}

void EgTextureManager::SetDevice(IDirect3DDevice9* pDevice)
{
	if(pDevice && !m_pDevice) m_pDevice = pDevice;
}

EgTexture* EgTextureManager::CreateTexture(char* pFilename, D3DCOLOR clrColorKey)
{
	EgTexture* pTemp = NULL;
	vector<EgTexture*>::iterator vItor;
	if(m_vTextures.size() > 0)
	{
		for(vItor = m_vTextures.begin(); vItor != m_vTextures.end(); vItor++)
		{
			pTemp = *vItor;
			if(stricmp(pTemp->GetFilename(), pFilename) == 0)
				return pTemp;
		}
	}

	pTemp = new EgTexture;
	pTemp->Create(m_pDevice, pFilename, clrColorKey);
	m_vTextures.push_back(pTemp);

	return  pTemp;
}

EgTexture* EgTextureManager::GetTexture(char* pFilename)
{
	EgTexture* pTemp = NULL;
	vector<EgTexture*>::iterator vItor;
	for(vItor = m_vTextures.begin(); vItor != m_vTextures.end(); vItor++)
	{
		if(stricmp(pTemp->GetFilename(), pFilename) == 0)
			return pTemp;
	}

	return NULL;
}

// Using it:

EgTextureManager g_TextureMgr;
...
g_TextureMgr.SetDevice(g_Engine.GetDevice());
g_TextureMgr.CreateTexture("cursor.png");
When I try to use this, it loads the app fine, but I can''t get the texture. Then, after I close it, I get an error message box (something about invalid block).
Advertisement
The problem with your destructor is that once you erase vItor, it is invalidated, and the post-increment operator is undefined. That is why you are getting errors on destruction. You should probably delete from the end going to the front, which will only invalidate the current iterator. Just store the previous iterator before erasing. If you''re at the beginning, break the loop.

As for not being able to get the texture, do you mean it returns NULL?
Nope, I just figured out that the problem with that was I was trying to display it with ID3DXSprite::Draw(), using NULL as the color (oops :D). As for deleting from end to begin, would I do this:
EgTextureManager::~EgTextureManager(){	EgTexture* pTemp = NULL;	vector<EgTexture*>::iterator vItor;	for(vItor = m_vTextures.end(); vItor != m_vTextures.begin(); vItor--)	{		pTemp = *vItor;		m_vTextures.erase(vItor);		delete pTemp;	}}

When I debug, it gives me an error on this line of the XUTILITY file:
_STD_BEGIN		// TEMPLATE FUNCTION copytemplate<class _II, class _OI> inline	_OI copy(_II _F, _II _L, _OI _X)	{for (; _F != _L; ++_X, ++_F)		*_X = *_F; // <-- this line here	return (_X); }

Thanks

[edited by - Programmer16 on June 1, 2004 6:59:29 PM]
quote:Original post by Programmer16
As for deleting from end to begin, would I do this:

<snip snip>

end() isn't actually a valid iterator, hence why it is used as the loop control. And I retract what I said early, anyway, it's a bad solution Loop the vector and just delete the pointers. The vector destructor will handle the rest.

[edited by - Zipster on June 1, 2004 7:14:21 PM]
quote:Original post by Programmer16
EgTexture* EgTextureManager::GetTexture(char* pFilename){	EgTexture* pTemp = NULL;	vector<EgTexture*>::iterator vItor;	for(vItor = m_vTextures.begin(); vItor != m_vTextures.end(); vItor++)	{		if(stricmp(pTemp->GetFilename(), pFilename) == 0)			return pTemp;	}	return NULL;}

I can't get the texture.

You loop using the iterator but don't change the value of pTemp. It's set to NULL. You need to assign *vItor to pTemp.

Personally though, I tend to shy away from writing my own loops and make use of the standard library's algorithms.
class TextureFileNameEquals {    std::string m_name;public:    TextureFileNameEquals(const std::string& name) : m_name(name) {    }    bool operator()(const EgTexture* texture) {        std::string filename(texture->GetFileName());        return filename == m_name;    }};EgTexture* EgTextureManager::GetTexture(char* pFilename){    vector<EgTexture*>::iterator vItor =        std::find_if(m_vTextures.begin(), m_vTextures.end(), TextureFileNameEquals(pFileName));    if(vItor != m_vTextures.end())        return *vItor;    else        return NULL;}

So, find_if returns an iterator if the predicate functor returns true. In this case the functor compares the texture name with a name given to it in its constructor. If it doesn't find anything it will return the end() iterator.

You could do the same for your other loops.

[edited by - quorn on June 2, 2004 5:30:11 AM]
Edit: Okay, I see what you're saying.

[edited by - Programmer16 on June 2, 2004 1:30:36 PM]

This topic is closed to new replies.

Advertisement