Skip to main content
gamedev.net
🔒 Locked

dynamic array or vector?

Started by eldee 22 replies 900+ views
Original Post
eldee
eldee
versus thread? think again anyway, i've been thinking about changing over my vector of textures in my texture manager to a dynamic array. the reason is because for some odd reason i can't get my vector to retain information properly. for example, i'm trying to write a simple loop to check if a file has already been "loaded". each time a texture gets loaded, i store the file's location in a character array.
      
for(int j = 0; j < textures.size(); j++)
{
   if( strcmp( textures[j].location, sFileName ) == 0 ) // sFileName is passed into the function we're in

   {
       textures.insert( textures.end() );
       textures[ textures.size() - 1 ] = textures[j]; // i've overloaded the assignment operator to return *this

   }
}
    
everything looks correct, right? so why is it that when i check the data in textures[ j ], it is invalid (ie, holds garbage.. width/height/bpp is -1 for an unsigned int, location becomes 256 random characters, ect)? i've narrowed it down to the call to textures.insert().. whatever is happening under the hood of STL's insert() is corrupting my data (be it designed or not), and it's frustrating me to the point of considering dynamic arrays instead. Anybody ever run into this situation or have a suggestion for me to get this working properly? [edit: meh, figured code tags would save me from the italics.. guess not] -eldee ;another space monkey; [ Forced Evolution Studios ]

::evolve:: Do NOT let Dr. Mario touch your genitals. He is not a real doctor! [edited by - eldee on May 21, 2003 5:49:32 PM] [edited by - eldee on May 21, 2003 5:59:15 PM]

daerid
daerid
please edit your post and use the [ source][/ source] tags
daerid@gmail.com
eldee
eldee
quote:
Original post by daerid
please edit your post and use the [ source][/ source] tags


okay, did you have anything else to add? heh.. i was fixing it at the same time you were posting
Sneftel
Sneftel
I''m kind of confused as to what your code is doing here (posting more of the function, and the variable defs, would have been a good idea). I''ve never seen vector::insert(vector::iterator) before, and I can''t see it in the STL docs I''ve got... what are you doing with those two lines, and why not push_back()?


How appropriate. You fight like a cow.
daerid
daerid
thanks... now I can take a look and see what''s going on

hmmm... what''d I''d do is ditch the insert() call. That requires an iterator, and just tacking on another name to a vector is a bit trivial to get involved with vectors.

You could do something like this (also, if speed''s a concern, consider moving over from a std::vector to a std::map, with the key being the string that''s the filename, and the value being the resource instance.)


  
class ResourceManager
{
public:
Resource LoadFile( const std::string& filename );

private:
std::vector< std::string > mLoadedFiles;
};

Resource ResourceManager::LoadFile( const std::string& filename ) {
// do loading processing here

std::vector< std::string >::iterator file = mLoadedFiles.begin();
std::vector< std::string >::iterator end = mLoadedFiles.end();
for( ; file != end; ++file ) {
if( stricmp( filename.c_str(), file->c_str() ) == 0 ) {
// file''s already been loaded, return previous instance

return Resource( filename ); // or something

}
}
// load new Resource

mLoadedFiles.push_back( filename );
}


daerid@gmail.com
Zipster
Zipster
quote:
I''ve never seen vector::insert(vector::iterator) before, and I can''t see it in the STL docs I''ve got...

The full declaration is iterator insert(iterator it, const T& x = T());, so he''s simply creating a default object just before end().

However, I don''t think end() is a valid iterator for insert, which might be why it''s ruining your data. push_back is what you want for end insertions.
daerid
daerid
quote:
Original post by Zipster
The full declaration is iterator insert(iterator it, const T& x = T());, so he's simply creating a default object just before end().

However, I don't think end() is a valid iterator for insert, which might be why it's ruining your data. push_back is what you want for end insertions.


end() is a valid iterator for inserts. end() returns an iterator, so by definition it must be valid.

[edited by - daerid on May 21, 2003 7:24:16 PM]
daerid@gmail.com
eldee
eldee
okay.. thats not working
here's my exact code for those that wanted it

    
texture_s new_texture;

static int f = 0;

Log->Write(LOG_ERROR, "loop %d", f);
f++;
if(textures.size() == 0)
{
Log->Write(LOG_ERROR, "texture vector is empty, creating first texture.");
}
else
{
for(int j = 0; j < textures.size(); j++)
{
Log->Write(LOG_ERROR, "sFileName = %s, textures[%d].location = %s", sFileName, j, textures[j].location);
if(strcmp(sFileName, textures[j].location) == 0) // sFileName is passed into the function we're in

{
new_texture.BPP = textures[j].BPP;
new_texture.width = textures[j].width;
new_texture.height = textures[j].height;
new_texture.size = textures[j].size;
sprintf(new_texture.location, textures[j].location);
textures.push_back(new_texture);
Log->Write(LOG_ERROR, "width1 %d, width2 %d", new_texture.width, textures[ textures.size() - 1].width);
return true;
}
j++;
}
}


and here's the output of my log, you can see that the "location" at element "0" just disappears .

(note: my log outputs to HTML format, so this will look sorta funky.. the timestamp above the event is the corresponding one, however timestamps arent really needed for this problem.

edit: okay that looked like crap.. here's a link to the log file on my web site
click here for log

-eldee
;another space monkey;
[ Forced Evolution Studios ]

::evolve::

Do NOT let Dr. Mario touch your genitals. He is not a real doctor!


[edited by - eldee on May 21, 2003 9:17:38 PM]

eldee
eldee
alright, lets try again...
i put together some very simple code in a console app to see if maybe i could isolate the problem. here it is:

        
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class texture_s
{
public:
unsigned int width,

height,
BPP,
ID,
size; // size in bytes

string location; // where was the original file located? this will help us avoid redundancy and bloating


texture_s() { }
texture_s(const texture_s&) { }
texture_s& operator =(const texture_s&) { return *this; }
~texture_s() {}

};
vector <texture_s> textures;

bool LoadTGA(string sFileName)
{
if(textures.size() == 0)
{
cout << "First pass, texture vector is empty" << endl;
}
for(int i = 0; i < textures.size(); i++)
{
cout << "textures[" << i << "].location = " << textures[i].location << ", sFileName = " << sFileName << endl;
if(textures[i].location == sFileName)
{
textures.push_back(textures[i]); // this should add a copy of textures[i] to the end of the vector

cout << "[" << sFileName << "] already loaded, adding a reference of ID " << textures[i].ID << " to element " << textures.size() - 1 << endl;
return true;
}
}
cout << "-------------------------------------------------------------------------\n";
textures.insert(textures.end());
textures[textures.size() - 1].BPP = 32;
textures[textures.size() - 1].width = 128;
textures[textures.size() - 1].height = 128;
textures[textures.size() - 1].size = 48000;
textures[textures.size() - 1].location = sFileName;
textures[textures.size() - 1].ID = textures.size();
//cout << "Adding texture [" << textures[textures.size() - 1].location << "] with ID " << textures[textures.size() - 1].ID << endl;

return true;
}

int main()
{
LoadTGA("Test1.tga");
LoadTGA("Test2.tga");
LoadTGA("Test3.tga");
LoadTGA("Test4.tga");
LoadTGA("Test5.tga");
LoadTGA("Test4.tga");
LoadTGA("Test6.tga");
return 0;
}


look at the output of that code when you compile it.. it looks like only the last element's information is getting saved

First pass, texture vector is empty
-------------------------------------------------------------------------
textures[0].location = Test1.tga, sFileName = Test2.tga
-------------------------------------------------------------------------
textures[0].location = , sFileName = Test3.tga
textures[1].location = Test2.tga, sFileName = Test3.tga
-------------------------------------------------------------------------
textures[0].location = , sFileName = Test4.tga
textures[1].location = , sFileName = Test4.tga
textures[2].location = Test3.tga, sFileName = Test4.tga
-------------------------------------------------------------------------
textures[0].location = , sFileName = Test5.tga
textures[1].location = , sFileName = Test5.tga
textures[2].location = Test3.tga, sFileName = Test5.tga
textures[3].location = Test4.tga, sFileName = Test5.tga
-------------------------------------------------------------------------
textures[0].location = , sFileName = Test4.tga
textures[1].location = , sFileName = Test4.tga
textures[2].location = , sFileName = Test4.tga
textures[3].location = , sFileName = Test4.tga
textures[4].location = Test5.tga, sFileName = Test4.tga
-------------------------------------------------------------------------
textures[0].location = , sFileName = Test6.tga
textures[1].location = , sFileName = Test6.tga
textures[2].location = , sFileName = Test6.tga
textures[3].location = , sFileName = Test6.tga
textures[4].location = Test5.tga, sFileName = Test6.tga
textures[5].location = Test4.tga, sFileName = Test6.tga
-------------------------------------------------------------------------
Press any key to continue

am i just using vectors totaly backward or something? i've never had problems with STL until this...

[edit: and before anybody tells me to change insert to push_back, i get the same problem with push_back]

[edited by - eldee on May 22, 2003 11:04:02 AM]
Qw3r7yU10p!
Qw3r7yU10p!
texture_s& operator =(const texture_s&) { return *this; }


thats your problem
eldee
eldee
quote:
Original post by petewood
texture_s& operator =(const texture_s&) { return *this; }


thats your problem


uh.. how do you figure? since i never even use the assignment operator in that code i just submitted....

anyway, i took it out of the class declaration just for grins, and it still outputs the same data (suprise suprise).

any other ideas?

-eldee
;another space monkey;
[ Forced Evolution Studios ]

::evolve::

Do NOT let Dr. Mario touch your genitals. He is not a real doctor!

Dire.Wolf
Dire.Wolf
He's right:


texture_s(const texture_s&) { }
texture_s& operator =(const texture_s&) { return *this; }

You aren't copying any of the member variables. Change your copy constructor and assignment operator to make the proper initializations.

  
texture_s::texture_s(const texture_s& r) : width(r.width),
height(r.height),
BPP(r.BPP),
ID(r.ID),
size(r.size),
location(r.location)
{
}

texture_s& texture_s::operator =(const texture_s& r)
{
if(this != &r)
{
width = r.width;
height = r.height;
BPP = r.BPP;
ID = r.ID;
size = r.size;
location = r.location;
}

return *this;
}


That should fix things.

[edited by - Digitalfiend on May 22, 2003 11:32:59 AM]
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
Dobbs
Dobbs
Your STL''s implementation of vector probably uses operator= behind the scenes.
Dire.Wolf
Dire.Wolf
Before you start saying your code doesn''t use the assignment operator, learn more about the STL. It most certainly uses the assignment operator.
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
Dire.Wolf
Dire.Wolf
Yes I know that but sooner or later he'll add a pointer to his texture and then he'll wonder why his code doesn't work anymore.

[edited by - Digitalfiend on May 22, 2003 11:44:18 AM]
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
Lektrix
Lektrix
Heh, he'd probably still just make a shallow copy of it in his copy constructor and assignment operator.

A reason for leaving it out is that I often find people adding members to their class after implementing their copy methods, and then forgetting to make copies of the new members.

[ Google || Start Here || ACCU || MSDN || STL || GameCoding || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on May 22, 2003 11:49:45 AM]
daerid
daerid
quote:
Original post by eldee
uh.. how do you figure? since i never even use the assignment operator in that code i just submitted....



You may not, but be assured that std::vector most definitely DOES use the = operator.

To be STL container compliant, your classes/types must be default constructable, copy constructable, and assignable thru the = operator.
daerid@gmail.com
Qw3r7yU10p!
Qw3r7yU10p!
quote:
anyway, i took it out of the class declaration just for grins, and it still outputs the same data (suprise suprise).


When you say ''surprise surprise'' it sounds as though you think my suggestion was wrong (possibly even stupid). It was definitely a bug in your code that I found for you. If you don''t understand why it was the problem then please ask.

quote:
any other ideas?

You''re coming across (to me at least) as being unappreciative of my efforts. Maybe be a bit more polite.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.