By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,046 Members | 2,058 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,046 IT Pros & Developers. It's quick & easy.

does this have undefined behaviour

P: n/a
Consider the following code:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
const double& ref = 100;
double& d = const_cast<double&>(ref);
cout << d << endl;
d = 1.1;
cout << ref << endl;

return EXIT_SUCCESS;
}

In both g++ and VC++ 2005 Express Edition, the output is
100
1.1

But my doubt is: "does using 'd' invoke undefined behavior or is it
valid."

double& d = const_cast<double&>(ref);

Kindly clarify.

Thanks
V.Subramanian
Dec 21 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
su**************@yahoo.com wrote:
Consider the following code:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
const double& ref = 100;
double& d = const_cast<double&>(ref);
cout << d << endl;
d = 1.1;
cout << ref << endl;

return EXIT_SUCCESS;
}

In both g++ and VC++ 2005 Express Edition, the output is
100
1.1

But my doubt is: "does using 'd' invoke undefined behavior or is it
valid."

double& d = const_cast<double&>(ref);
What you're doing here is changing the value of the temporary
bound to a const reference. Such temporary is not const, so,
changing its value by casting away const-ness should be OK.
I can't find any place in the Standard that would prohibit
such functionality. Then my guess is that it's allowed.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 21 '07 #2

P: n/a
On Dec 21, 5:04 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
subramanian10...@yahoo.com wrote:
Consider the following code:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
const double& ref = 100;
double& d = const_cast<double&>(ref);
cout << d << endl;
d = 1.1;
cout << ref << endl;
return EXIT_SUCCESS;
}
In both g++ and VC++ 2005 Express Edition, the output is
100
1.1
But my doubt is: "does using 'd' invoke undefined behavior or is it
valid."
double& d = const_cast<double&>(ref);

What you're doing here is changing the value of the temporary
bound to a const reference. Such temporary is not const, so,
changing its value by casting away const-ness should be OK.
I can't find any place in the Standard that would prohibit
such functionality. Then my guess is that it's allowed.
I think the OP might have thought that he actually changed the value
of "ref" (the constant one). I don't think he realized that a
temporary was created - therefore changing the value of "d" does
not change the value of "ref".

Regards,

Werner

Dec 21 '07 #3

P: n/a
werasm wrote:
On Dec 21, 5:04 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>subramanian10...@yahoo.com wrote:
>>Consider the following code:
>>#include <iostream>
#include <cstdlib>
>>using namespace std;
>>int main()
{
const double& ref = 100;
double& d = const_cast<double&>(ref);
cout << d << endl;
d = 1.1;
cout << ref << endl;
>>return EXIT_SUCCESS;
}
>>In both g++ and VC++ 2005 Express Edition, the output is
100
1.1
>>But my doubt is: "does using 'd' invoke undefined behavior or is it
valid."
>>double& d = const_cast<double&>(ref);

What you're doing here is changing the value of the temporary
bound to a const reference. Such temporary is not const, so,
changing its value by casting away const-ness should be OK.
I can't find any place in the Standard that would prohibit
such functionality. Then my guess is that it's allowed.

I think the OP might have thought that he actually changed the value
of "ref" (the constant one). I don't think he realized that a
temporary was created - therefore changing the value of "d" does
not change the value of "ref".
No, that's incorrect, IMO. First off, you can't change the value
of ref because it's a reference, it doesn't really have a value
(aside from the fact that it refers to some particular object).
The temporary created is of type 'double', it has initial value
of 100.00 and it starts its lifetime just before 'ref' is bound
to it. The integral expression '100' is the initialiser for that
temporary.

The temporary to which 'ref' is bound is not a const object. It
is perfectly OK to change its value. Whether it makes sense to
do so or not is another question, but the idea is the same as in

void foo(int const& rci)
{
int& ri = const_cast<int&>(rci);
ri = 666; /// Is this OK? -- I say, yes, it is!
}

#include <iostream>
#include <ostream>
int main() {
int a = 42;
std::cout << "Before a = " << a << std::endl;
foo(a);
std::cout << "After a = " << a << std::endl;
}

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 21 '07 #4

P: n/a
"su**************@yahoo.com, India" <su**************@yahoo.comwrote
in news:404f0505-3d9f-4173-8361-a0a328537882
@i29g2000prf.googlegroups.com:
Consider the following code:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
const double& ref = 100;
double& d = const_cast<double&>(ref);
Dangerous. You might attempt to modify what d refers to.
cout << d << endl;
d = 1.1;
Undefined behaviour. You are modifying a const object.
cout << ref << endl;

return EXIT_SUCCESS;
}

In both g++ and VC++ 2005 Express Edition, the output is
100
1.1

But my doubt is: "does using 'd' invoke undefined behavior or is it
valid."

double& d = const_cast<double&>(ref);
This isn't Undefined Behaviour. Attempting to modify what d refers to
is the Undefined Behaviour.
Dec 24 '07 #5

P: n/a
On Dec 21, 5:04 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
subramanian10...@yahoo.com wrote:
{
const double& ref = 100;
double& d = const_cast<double&>(ref);

What you're doing here is changing the value of the temporary
bound to a const reference. Such temporary is not const, so,
changing its value by casting away const-ness should be OK.
The temporary is const. See 8.3.5#5 [dcl.init.ref], last clause.

So the behaviour is undefined when the attempt is made to
modify d (the cast itself is fine though).
Dec 25 '07 #6

P: n/a
On Dec 22, 3:10 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
The temporary to which 'ref' is bound is not a const object. It
is perfectly OK to change its value.
Actually it is const, as per 8.3.5#5
the idea is the same as in

void foo(int const& rci)
{
int& ri = const_cast<int&>(rci);
ri = 666; /// Is this OK? -- I say, yes, it is!
}

#include <iostream>
#include <ostream>
int main() {
int a = 42;
std::cout << "Before a = " << a << std::endl;
foo(a);
std::cout << "After a = " << a << std::endl;
}
This code is OK; since a is an lvalue, a temporary
is not created.
Dec 25 '07 #7

P: n/a
Andre Kostur wrote:
"su**************@yahoo.com, India" <su**************@yahoo.comwrote
in news:404f0505-3d9f-4173-8361-a0a328537882
@i29g2000prf.googlegroups.com:
>Consider the following code:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
const double& ref = 100;
double& d = const_cast<double&>(ref);

Dangerous. You might attempt to modify what d refers to.
> cout << d << endl;
d = 1.1;

Undefined behaviour. You are modifying a const object.
> cout << ref << endl;

return EXIT_SUCCESS;
}

In both g++ and VC++ 2005 Express Edition, the output is
100
1.1

But my doubt is: "does using 'd' invoke undefined behavior or is it
valid."

double& d = const_cast<double&>(ref);

This isn't Undefined Behaviour. Attempting to modify what d refers to
is the Undefined Behaviour.
Could you please elaborate on why it is undefined behaviour?

Thanks.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 26 '07 #8

P: n/a
>
The temporary to which 'ref' is bound is not a const object. It
is perfectly OK to change its value. Whether it makes sense to
do so or not is another question, but the idea is the same as in
I think, as the temp object is that of an in-built type, it is fine.
But had it been that of a custom type, the temp object would have been
an constant object...
Dec 26 '07 #9

P: n/a
Rahul wrote:
>The temporary to which 'ref' is bound is not a const object. It
is perfectly OK to change its value. Whether it makes sense to
do so or not is another question, but the idea is the same as in

I think, as the temp object is that of an in-built type, it is fine.
But had it been that of a custom type, the temp object would have been
an constant object...
Any standard quote to support that claim?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 26 '07 #10

P: n/a
Rahul wrote:
>The temporary to which 'ref' is bound is not a const object. It
is perfectly OK to change its value. Whether it makes sense to
do so or not is another question, but the idea is the same as in

I think, as the temp object is that of an in-built type, it is fine.
But had it been that of a custom type, the temp object would have been
an constant object...
It's the other way around. It could work with a class type.

To provide lost context, we consider code like this:

const double& ref = 100; // *
double& d = const_cast<double&>(ref);
d = 1.1;

Clearly, line (*) is the important line. Its meaning is governed by
[8.3.5/5], which is too long to quote in full, so I cut out irrelevant
parts:

A reference to type ?cv1 T1? is initialized by an expression of type
?cv2 T2? as follows:
? If the initializer expression
? is an lvalue ...
? has a class type ... and can be implicitly converted to an lvalue ...
? Otherwise, the reference shall be to a non-volatile const type ...
? If the initializer expression is an rvalue, with T2 a class type, ...
? Otherwise, a temporary of type ?cv1 T1? is created and initialized
from the initializer expression using the rules for a non-reference
copy initialization (8.5). The reference is then bound to the
temporary. If T1 is reference-related to T2, cv1 must be the same
cv-qualification as, or greater cvqualification than, cv2; otherwise,
the program is ill-formed.

In line (*), the initializer is an rvalue not convertible to an lvalue. That
puts us in the first "Otherwise" item. Also, it is not of class type, which
puts us in the "Otherwise" subitem. The provision then states that the
const reference is bound to a temporary of type cv1 T1 (in our case that is
a temporary of type const double). Modifying that temporary under a
different handle is undefined behavior.
Now consider a class type ClassType:

const ClassType & ref = some_expression_of_ClassType;
ClassType & handle = const_cast< ClassType& >( ref );
handle = some_other_expression;

We then have the following verions of [8.5.3/5]:

A reference to type ?cv1 T1? is initialized by an expression of type
?cv2 T2? as follows:
? If the initializer expression
? is an lvalue ...
? has a class type ... and can be implicitly converted to an lvalue ...
? Otherwise, the reference shall be to a non-volatile const type ...
? If the initializer expression is an rvalue, with T2 a class type,
and ?cv1 T1? is reference-compatible with ?cv2 T2,? the reference is
bound in one of the following ways (the choice is
implementation-defined):
? The reference is bound to the object represented by the rvalue (see
3.10) or to a sub-object within that object.
? A temporary of type ?cv1 T2? [sic] is created, and a constructor is
called to copy the entire rvalue object into the temporary. The
reference is bound to the temporary or to a sub-object
within the temporary.
...
...

In this case, depending on the choice of the implementation, the reference
is either bound to a temporary of type ClassType or of type const ClassType
(if the implementation chose the second alternative). Therefore, it is
implementation-defined whether the code has undefined behavior for class
types. (I have a vague recollection that the second alternative is slanted
for elimination in the next version of the standard. In that case, the code
would have well-defined behavior for class types and undefined behavior for
built-in types.)
Best

Kai-Uwe Bux
Dec 27 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.