Stuart Golodetz <sgolodetz@NdOiSaPlA.pMiPpLeExA.ScEom> wrote in
news:R-GdnTwvE6f9MEPWnZ2dnUVZ7vednZ2d@pipex.net:
Adam Nielsen wrote:
struct fixedLength {
std::string& data;
int len;
fixedLength(std::string& data, int len) :
data(data),
len(len)
{
}
};
std::istream& operator >> (std::istream& s, const fixedLength& n)
{
n.data.resize(n.len);
s.read(const_cast<char *>(n.data.c_str()), n.len);
return s;
}
Why "const fixedLength& n"? If you're reading into it, isn't the
implication that it's going to change? So "fixedLength& n" would
seem more intuitive.
That's what I thought too, but the way C++ operators seem to work it
has to be const for it to be called implicitly. I think. Actually
I'm not sure, but it didn't work without the const and it did with it
:-) Maybe because you're passing in a reference to a temporary.
But logically you're not changing the fixedLength object itself
(because the length is the same) so I think it can be const. You'll
note the std::string reference is non-const, because this sits
"outside" the fixedLength class and can be changed. I agree it may
be a little unintuitive, but like I say, it didn't work without the
const ;-)
My bad, I just looked at the operator>> when I made that comment
instead of looking at the usage. The issue is the old 'you can't bind
a non-const reference to a temporary', yes. Ignore me!
Also, could you write "&n.data[0]" instead of
"const_cast<char*>(n.data.c_str())" to avoid the const_cast?
Hmm, good idea, I'd never noticed that. I understand why operator[]
would return a non-const value, but then why would both c_str() and
data() return const values?
Good question -- judging by a bit of Googling, I suspect it might be
something to do with designing the interface in a way that's more
convenient for copy-on-write implementations (if you return const char
* from c_str() and data() then you don't need to make a copy at that
point as you can assume the string won't be changed). But the honest
answer is I don't know :) So if anyone else can clarify...?
The current standard (2003) explicitly says "The program shall not alter
any of the values stored in the array" returned by c_str() and data().
The wording also seems to allow returning a pointer to a *copy* of the
string content. I guess this is for better support of COW and maybe also
for non-contiguous std::string storage (though this seems to be
implicitly forbidden by defining operator[] via data()[pos] (which would
not really work for non-const version however)).
Thus, to avoid problems with a potential implementation using COW, one
should use &str[0] instead of c_str() or data(). Because of multi-
threading complications COW has fallen out of fashion, but better be safe
than sorry.
OTOH, to my knowledge all current std::string implementations are using
contiguous storage and this will be explicitly mandated by the next
standard, so one should not worry about that point.
hth
Paavo