Reputation: 51
I have searched a lot for this type of questions but got no satisfied answers.
I am working on a function to write a vector container to a binary file using ofstream::write method in C++.
#include <vector>
#include <fstream>
typedef std::vector<unsigned char> byteArray;
byteArray data;
data.push_back('a');
data.push_back('b');
data.push_back('c');
data.push_back('d');
std::ofstream fout("out_file", std::ios::out | std::ios::trunc | std::ios::binary);
// I know the right way should be as following:
fout.write((char *)&data[0], data.size());
// But what I cannot understand is why the following expression is wrong, since gcc compiler says
// invalid cast from type ‘__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >’ to type ‘char*’
for(auto iter = data.begin(); iter != data.end(); iter++)
{
fout.write((char *)iter, 1);
}
fout.close();
As I understand, iterator iter is a pointer which points to one element in vector 'data'. So I think that (char *) iter would re-interpret the underlying data type as char, then it should satisfy the parameter requirement of fout.write. But actually, this is not the case. I am also very confused that gcc says iter is a type of iterator<unsigned char*, std::vector >, right? Should the iter not be unsigned char * type?
what do I get wrong? Thanks a lot for any help.
Upvotes: 0
Views: 417
Reputation: 74078
A pointer may be used as an iterator, but an iterator need not be a pointer.
An iterator behaves more or less like a pointer by providing operations for dereferencing operator*()
, incrementing operator++()
, etc., see requirements of e.g. LegacyInputIterator
Although the concrete definitions change over time, see std::input_or_output_iterator for definitions in C++20.
Upvotes: 1
Reputation: 63912
As I understand, iterator iter is a pointer
It is not. std::vector::iterator
is an unspecified type.
You can expect it to have some pointer-like properties, but you should make no assumptions about what specific type it may be.
Since you need a pointer, dereference the iterator and take the address of that result. That's a pointer.
fout.write((char *)&*iter, 1);
Better still, use C++ casts instead of the hard-to-track C casts.
fout.write( static_cast<char*>(&*iter), 1 );
Even safer (Martin York is always a precious gem) -- don't assume the size of the contained type. It could change in the future. This change adds no overhedd.
fout.write( static_cast<char*>(&*iter), size_of(byteArray[0]) );
Upvotes: 2