views:

217

answers:

5
+1  Q: 

vector and dumping

From what i know a vector is guaranteed to be continuous and i can write a chunk of memory to it and do send of fwrite with it. All i need to do is make sure i call .resize() to force it to be the min length i need then i can use it as a normal char array? would this code be correct

v.resize(numOfElements);
v.clear(); //so i wont get numOfElements + len when i push back
vector<char>v2;
v2.resize(numOfElements*SizeOfType);
while(...)
{
...
v.push_bacK(x); 
}
compress(&v2[0], len, &v[0], len);
fwrite(&v2[0], ....)

noting that i never push back or pop v2 i only resize it once and used it as a char array. Would this be safe? and if i also dumped v that would also be safe(i do push back and clear, i may dump it for testing)

+4  A: 
v.resize(numOfElements);
v.clear(); //so i wont get numOfElements + len when i push back

Well, that above code snippet is in effect allocating and creating elements, just to destroy them again. It's in effect the same as:

v.reserve(numOfElements);

Just that this code is way faster. So, v.size() == 0 in both cases and v.capacity() might be the same as numOfElements in both cases too (although this is not guaranteed). In the second case, however, the capacity is at least numOfElements, which means the internal buffer will not be reallocated until you have push_back'ed that many elements to your vector. Note that in both cases it is invalid if you try accessing any elements - because there are zero elements actually contained.

Apart from that, i haven't figured a problem in your code. It's safe and i would encourage it so use it instead of a raw new or malloc because of the added safeties it provides. I'm however not sure what you mean by "dump v".

Johannes Schaub - litb
acidzombie24
.clear() will make .size() == 0. that means that you can not index any elements, because there are none. but in that case, you can just do .reserve(N) too, which will in effect be the same. note that i wasn't sure that .clear() really doesn't touch .capacity()
Johannes Schaub - litb
often it doesn't (as in your case). but i've looked it up in the standard now to be completely sure, and there is no guarantee about that
Johannes Schaub - litb
thanks jwfearn for adding clearness to it. This reserve/resize stuff seems to be pretty confusing. I've often seen .reserve used when .resize should be used, and i'm having problems with what .resize does wrt .capacity too :) let's hope we have it clear now
Johannes Schaub - litb
acidzombie24, oh wait. you should only do the reserve with v of course. the v2 should be resized (or alternatively put to that length at creation time already using a length as constructor argument),because you actually want the vector to have that specific size you tell it to have from the start on
Johannes Schaub - litb
resize( n) - make the vector contain exactly n elements (may destroy or create new elements as needed). reserve( n) - simply ensure that the capacity of the backing memory is at least enough for n elements. The number of 'active' elements in the vector does not change. Think of reserve() as a hint.
Michael Burr
Also, clear() should not change the capacity() of a vector. My reading of the standard does not make this 100% clear to me, but it is apparently clear to PJ Plauger, who knows an awful lot about this stuff: http://www.cpptalk.net/is-clear-allowed-to-deallocate-vt23233.html
Michael Burr
Michael Burr. do you mean something is wrong with my exlanation of resize(n) ? i mean, resize does just allocate and create exactly n elements, but them the clear destroys them again (but not necassarily deallocate the storage. tho pj plauger as you say says it doesn't. i'll have a look at him)
Johannes Schaub - litb
Michael Burr, i was in the impression v is empty prior his code. so the .reserve would leave it empty (thus .size() == 0). acidzombie, is this true? or does v contain something prior to your code?
Johannes Schaub - litb
Michael, thanks for the link btw :)
Johannes Schaub - litb
i see. well the argument that .begin() must remain a valid validator is actually quite good. i'll update my answer soon, reading in the standard again about what exactly constitutes "valid iterators". have fun (though it's of course still a bad idea to first .resize, but then .clear :))
Johannes Schaub - litb
@litb - I was not saying that there was anything wrong with the discussion, I was just trying to make a clear summary of resize() vs. reserve(). You are correct that resize() followed by clear() is essentially the same as reserve().
Michael Burr
+2  A: 

Indeed, std::vector is guaranteed to be contiguous, in order to be layout-compatible with a C array. However, you must be aware that many operations of the vector invalidate all pointers pointing to its elements, so you'd better stick to one type of use: avoid mixing pointer arithmetic and method calls on the vector.

Apart from that is perfectly correct, except the first line : what you want is

v.reserve(numOfElements);

which will allocate enough place to store numOfElements into the vector, whereas

v.resize(numOfElements);

will do the following:

// pseudo-code
if (v.size() < numOfElements)
    insert (numOfElements - size) elements default 
    constructed at the end of the vector

if (v.size() > numOfElements)
    erase the last elements so that size = numOfElements

To sum up, after a reserve you are sure that vector capacity is superior or equal to numOfElements, and after a resize you are sure that vector size is equal to numOfElements.

Luc Touraille
A: 

Yes you use a vector of char as a buffer for reading raw input.

// dynamically allocates a buffer of 10,000 char as buffer
std::vector<char>   data(10000);

fread(&data[0], sizeof(char),data.size(),fp);

I would not use it for reading any non POD data type directly into an vector though.

You could potentially use a vector as a source for a write.
But I would be very carefull how you read that back in (it may be easier to serialize it).

fwrite(&data[0], sizeof(char),data.size(),fp);
Martin York
A: 

You're replacing reserve() with resize, you may as well replace

vector<char> v2

with

vector<Type> v2

This should simplify the code a tiny bit.

To be frank, it's the oddest use of vectors I've ever seen, but it probably will work. Are you sure you don't want to go with new char[size] and some sort of auto pointer from boost?

Arkadiy
+2  A: 

For something like this I would personally use a class like STLSoft's auto_buffer<>:

As a disclaimer - I don't use the actual STLSoft library version, I've adapted my own template that is quite similar - I started from the Matthew Wilson's (the STLSoft author's) book "Imperfect C++".

I find it useful when I really just want a plain-old C array, but the size must be dynamic at runtime. auto_buffer<> is safer than a plain old array, but once you've constructed it you have no worries about how many elements are there or not - it's always whatever you constructed it with, just like an array (so it's a bit less complex than vector<> - which is appropriate at times).

The major downside to auto_buffer<> is that it's not standard and it's not in Boost, so you either have to incorporate some of STLSoft into your project or roll your own version.

Michael Burr