Vector reserve & iterator
The small but important fact caused me many hours trying to figure out why my code didn't work... :SICK:
todoVector.push_back(ModelFile(masterModelName));
todoVector.reserve(10000);
for(todoVector_itr=todoVector.begin(); todoVector_itr!=todoVector.end(); ++todoVector_itr){
for(name_itr=todoVector_itr->vectorINCLUDE.begin();name_itr!=todoVector_itr->vectorINCLUDE.end();++name_itr){
todoVector.push_back(ModelFile(*name_itr));
}
}
I finally figured out that if the ends of the vector changed, it invalidates the iterator. By using reserve, you solve that problem.
So when you reseve, does it actually use that much memory when you reserve it? would using a larger value hog up memory?
I noticed that the capacity changed to the value that is reserved.
So what happens if the data overflows the pre-reserved size? your code must explicitly check for this?
Thanks.
[969 byte] By [
rssmps] at [2007-11-11 7:32:37]

# 1 Re: Vector reserve & iterator
I don't understand your code. If the vector is empty, then there's no point in testing its bounaries in a for loop that increments its iterator. What you need is a loop that simply calls vect.push_back() without using iterators in the for-loop condistion:
for (int i=0; i<SOME_VALUE; ++i;)
{
vect.push_back(something);
}
There's no need to call reserve() before push_back, unless you're using iterators that might become invalidated, but once more: this shouldn't happen anyway.
Danny at 2007-11-11 21:02:03 >

# 2 Re: Vector reserve & iterator
oops, I left out a line...that's why it's not making sense.
should be this:
// insert the first file
todoVector.push_back(ModelFile(masterModelName));
for(todoVector_itr=todoVector.begin(); todoVector_itr!=todoVector.end(); ++todoVector_itr){
// process the current file
process(*todoVector_itr);
// add each file referenced in the current file to list of files to examine.
for(name_itr=todoVector_itr->vectorINCLUDE.begin();name_itr!=todoVector_itr->vectorINCLUDE.end();++name_itr){
todoVector.push_back(ModelFile(*name_itr));
}
}
Ok, this is how it is supposed to work.
Initially, I push one ModelFile on to the vector.
I then go into the first for loop to process all the files in the todovector. There is at least one file to process.
Each ModelFile obj has a vectorINCLUDE to keep track of all the files referenced in the current file. Process() adds to vectorInclud any filenames mentioned in the current file.
After a file is processed, I need to add all the files in the vectorINCLUDE to the todovector. VectorInclude is a string vector so that's why the second for loop is also pushing Modelfile obj.
So this is where the todoVector_itr iterator invalidating occurs. If I don't specify a reserve size, the first cycle of the 2nd for loop processes fine. But the second cycle will then cause an error because the outer loop iterator was setup before the second push_back of the inner for loop. This 2nd push somehow invalidates the iterator.
my fix came from here: http://www.sgi.com/tech/stl/Vector.html
A vector's iterators are invalidated when its memory is reallocated. Additionally, inserting or deleting an element in the middle of a vector invalidates all iterators that point to elements following the insertion or deletion point. It follows that you can prevent a vector's iterators from being invalidated if you use reserve() to preallocate as much memory as the vector will ever use, and if all insertions and deletions are at the vector's end.
I suppose I could get around this problem and brute force it with a while less then todovector.size type of loop. But this way, I learn a little more. :)
In general you want to use iterators rather the a while loop with counter right?
rssmps at 2007-11-11 21:03:04 >

# 3 Re: Vector reserve & iterator
I still don't understand the code. What exactly is vectorINCLUDE? A vector member inside another vector? In any case, the loop is wrong and trying to workaround the bug by using reserver is a bad idea. If you know thet size at compile time, why use a container in the first place? You can use an ordinary array (not that I'm suggesting this). Also, if the second loop might be using a stale iterator, then it's most likely a logical flaw in the design. You can't use an iterator for one loop in another loop, regardless of whether the two loops are nested. In short, please explain what you're trying to do. I don't follow yoru terminology. Most specifically: what is "each file referenced in the current file"? How are the files referenced from the current file? And what does it mean to examine them later? Also, if the second vector is a vector of strings, why are you inserting a modelfile object in the push_back operation?
Danny at 2007-11-11 21:04:09 >

# 4 Re: Vector reserve & iterator
ok, suppose I have the following 3 files.
filein.txt:
123
345
fileb.txt
324
filec.txt
12
fileb.txt:
123465
34565
324789
12
filec.txt:
123.123
345.2
324.6
12.9
The ModelFile object has a vector<strings> vectorINCLUDE.
I don't know beforehand how many files there are. I need to process the first file to know exactly how many. In this example, I should have three ModelFile obj. (filein, fileb, filec).
todoVector is a global vector<ModelFile>. As each text file is processed, any filename (eg. fileb.txt) called out in the file being processed (filein.txt) needs to be added to the global todoVector so that its contents can be examined later. Since I read a string from the files, that's why I have to push ModelFile(somestring).
so my code starts with:
ModelFile filea("filein.txt") and push that in to the global todovector.
I then setup the global vector iterator (with only one item initially).
after process() command is done, filein.vectorINCLUDE then will have two items (fileb.txt & filec.txt)
this is where the second loop comes in. I need to turn the two string names into ModelFIle obj and push those on to the global todovector. This is because after I'm done with reading filein.txt, I need to then read fileb.txt and filec.txt and so on...
in the case of fileb, and filec, there are no filename strings so nothing needs to be added the the global vector.
does this make more sense?
rssmps at 2007-11-11 21:05:09 >

# 5 Re: Vector reserve & iterator
OK, why don't you simply extend process() so that it inserts the file names to the vectorINCLUDE object in addition the its current functionality? Notice that the iterator used in the first loop is irrelevant for the second loop: you're pushing_back a string to an embedded vector inside the primary vector, and the two vectors are certainly independent with respect to their sizes. The reserve() hack merely masks a serious logical flaw: if the global vector is empty, for instance, this doesn't mean that its vectorINCLUDE data member must be empty too, right? So you need to use a different iterator here, the one pointing the gloabalvec.includes::iterator, as opposed to globalvec::iterator.
Danny at 2007-11-11 21:06:08 >
