auto_array_ptr/reading into a vector
Why isn't there an auto_array_ptr in C++?
Or, to put the question another way, how do I read binary data from a file into a vector?
The reason these two questions seem related to me is because I've been writing a simple ZIP file reader (I'm basically a C programmer), and if I want to read binary data into a dynamic array I seem to have 3 choices: use C pointers and have an exception-safety nightmare, write my own auto_array_ptr or something like this:
std::vector<char> data(size);
input_stream.read(&data[0], size);
Which I don't like for two reasons: first, I don't believe &data[0] is guaranteed to work on all implementations and second I think the std::vector constructor will initialize the array which is a waste of time.
However, auto_array_ptr also isn't in boost which leads me to think that there is a really good way to do this or a really good reason why the boost people haven't put it in (I think it has been proposed).
Because there's std::vector, which is guaranteed to have continguous memory.
std::ifstream input_stream("filename", std::ios_base::binary);std::vector<char> data((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
Quote:Original post by ZQJ
Which I don't like for two reasons: first, I don't believe &data[0] is guaranteed to work on all implementations
As long as the vector is not empty, yes it is guaranteed to work on all standards conforming implementations.
Quote:and second I think the std::vector constructor will initialize the array which is a waste of time.
Let me get this straight. You're worried about the cost of default-initialising a vector when you're about to read into it from a file? You do realise that file I/O is orders of magnitude slower than memory access, right? That default initialisation is going to be something like 0.1% of the total time spent in that section of code. Don't worry about it.
Enigma
Quote:Original post by SiCrane
Because there's std::vector, which is guaranteed to have continguous memory.std::ifstream input_stream("filename", std::ios_base::binary);std::vector<char> data((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
Thanks, but how do I read a set number of bytes into memory that way? (Ok, I could do the other way of course).
Quote:Original post by Enigma
Let me get this straight. You're worried about the cost of default-initialising a vector when you're about to read into it from a file? You do realise that file I/O is orders of magnitude slower than memory access, right? That default initialisation is going to be something like 0.1% of the total time spent in that section of code. Don't worry about it.
True, I just hate wasted program time in general :)
Quote:Original post by ZQJQuote:Original post by SiCrane
Because there's std::vector, which is guaranteed to have continguous memory.std::ifstream input_stream("filename", std::ios_base::binary);std::vector<char> data((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
Thanks, but how do I read a set number of bytes into memory that way? (Ok, I could do the other way of course).
One of many ways:
template < typename value_t >class istreambuf_generator { typedef value_t value_type; typedef std::istreambuf_iterator< value_type > iterator_type; typedef std::istream istream_type; iterator_type i;public: istreambuf_generator( istream_type & istream ) : i( istream ) { } value_type operator()( void ) { assert( i != iterator_type() && "Tried to read past EOF" ); value_type value = *i; ++i; return value; }};std::ifstream input_stream("filename", std::ios_base::binary);std::size_t size = ...;std::vector< char > data( size );std::generate( data.begin() , data.end() , istreambuf_generator< char >( input_stream ) );
Quote:Quote:Original post by Enigma
Let me get this straight. You're worried about the cost of default-initialising a vector when you're about to read into it from a file? You do realise that file I/O is orders of magnitude slower than memory access, right? That default initialisation is going to be something like 0.1% of the total time spent in that section of code. Don't worry about it.
True, I just hate wasted program time in general :)
Of course, by worrying about trivial things like this, you waste your time, which in turn means you're unable to spend that time optimizing someplace it'll count - the end result being more wasted program time total than if you had properly allocated your time.
If you're using Boost, there's also boost::scoped_array, which would be just like a theoretical std::auto_array[_ptr] minus the "Assignment-that-really-steals-ownership" and "Release" semantics.
Quote:Original post by SiCranestd::vector<char> data((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
Why is the extra set of parentheses around the first constructor argument necessary? Without it, VC++ sees the line as a function prototype, rather than a variable declaration, but why does the extra set of brackets fix this?
Quote:Original post by bakery2k1Quote:Original post by SiCranestd::vector<char> data((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
Why is the extra set of parentheses around the first constructor argument necessary? Without it, VC++ sees the line as a function prototype, rather than a variable declaration, but why does the extra set of brackets fix this?
You are very correct about the line being a function prototype without the parentheses. It has to do with the "rule", if it looks like a function prototype, it is a function prototype. However, parentheses around the parameter type and name in a function declaration is illegal, so the only way to intepret that line would be a variable definition which passes values to the constructor.
Quote:Original post by Brother BobQuote:Original post by bakery2k1Quote:Original post by SiCranestd::vector<char> data((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
Why is the extra set of parentheses around the first constructor argument necessary? Without it, VC++ sees the line as a function prototype, rather than a variable declaration, but why does the extra set of brackets fix this?
You are very correct about the line being a function prototype without the parentheses. It has to do with the "rule", if it looks like a function prototype, it is a function prototype. However, parentheses around the parameter type and name in a function declaration is illegal, so the only way to intepret that line would be a variable definition which passes values to the constructor.
That's all true and all, but it's totally opaque unless you've gotten bitten by it before.
As I recall, the Exceptional C++ article about it suggests the following instead:
std::istreambuf_iterator<char> b(input_stream), e;std::vector<char> data(b,e);
Quote:Original post by me22
That's all true and all, but it's totally opaque unless you've gotten bitten by it before.
As I recall, the Exceptional C++ article about it suggests the following instead:std::istreambuf_iterator<char> b(input_stream), e;std::vector<char> data(b,e);
I have made the mistake of making the function instead of the object quite a few times, and personally I think the cleanest solution is what SiCrane posted. Scott Meyers also suggests your appoach in Effective STL, but as I understand it mainly due to the fact that some old compilers just can't handle SiCrane's version, so it will be more portable.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement