Re: GotW #88: Is it safe to const_cast a reference to a temporary?
On Feb 2, 10:37 pm, "Alf P. Steinbach" <al...@start.no> wrote:
* Niels Dekker - no return address:
Herb Sutter wrote a new Guru-of-the-Week column last month, GotW #88,
about binding a temporary object to a reference-to-const. Now if this
temporary isn't const, is it safe to const_cast the reference?
#include <string>
#include <cassert>
using std::string;
string f() { return "abc"; }
void h() {
const string& s1 = f();
const string& s2 = s1;
const_cast<string&>(s1) = "new value!"; // Safe?
Not in standard C++, although it might be safe with a
particular compiler.
This has always been my believe as well, and I'm almost sure
that I once read somewhere in the standard something to the
effect that any attempt to modify a temporary (e.g. by such
tricks) was undefined behavior. The last time I looked for it,
however, I couldn't find it. So could you tell me where in the
standard this is forbidden. It's tricky, because you are
allowed to call a non-const function on a temporary, and the
assignment operator of std::string is a non-const function.
There are really two separate questions: what about:
int const& i = 42 ;
const_cast< int& >( i ) = 0 ;
I certainly hope that it's illegal, but that was the case I was
actually looking for, and couldn't find.
It's frustrating me, because I really want the example with int
to be undefined behavior, and I'm sure that it is, but I can't
find the words in the standard to back it up.
The short of it is that you're misinforming the compiler, and
the almost as short of it is that the compiler is free to
optimize away the call to f and e.g. substitute the value
string("abc") wherever s1 and s2 are used.
This isn't generally true; a compiler cannot assume that because
a reference to const evaluated to a certain value once, it will
evaluate to that value a second time. The question is: when can
it make such assumptions?
The bit-longer of it is that the temporary was const to begin
with (the temporary bound to the reference, not the temporary
returned by the function, although they might end up being the
same), and you can't cast away /original/ const'ness with
portable well-defined result.
Except that in the example, the temporary wasn't const to begin
with. The function f() retuns an std::string, and not an
std::string const. If f() had returned an std::string const,
then the code definitely has undefined behavior.
Again, we have two different cases to consider. Temporaries of
non-class types are never const.
assert(s1 == "new value!"); // Okay?
assert(s2 == "new value!"); // Okay?
}
See also:
GotW #88 - A Candidate For the "Most Important const."
http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry
Would IMHO be better if Herb posted his GotW questions here,
as he did for the first few,
More than just a few:-). Certainly, if he wants people to
comment on them, or even read them, he should post them
somewhere that people read regularly. Nothing against Herb's
site, but I don't visit it every week just to see if there's
anything new.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34