Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Mutability of temporary variables

Reply
Thread Tools

Mutability of temporary variables

 
 
kyle
Guest
Posts: n/a
 
      11-19-2011
Consider following code:

int main() {
const int& c = int();
int& m = const_cast<int&>(c);
m = 4;
}

The object of the snippet is to get a mutable reference to a temporary.
This cant be done directly because non-const reference cannot bind to
temporary, but we should be OK with casting away constness of reference
'c' since it doesn't actually refer to const object.

Temporaries are mutable, so in whole my snippet is legal C++. Am i correct?

--
kyle
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      11-19-2011
On 11/19/2011 7:33 AM, kyle wrote:
> Consider following code:
>
> int main() {
> const int& c = int();
> int& m = const_cast<int&>(c);
> m = 4;
> }
>
> The object of the snippet is to get a mutable reference to a temporary.
> This cant be done directly because non-const reference cannot bind to
> temporary, but we should be OK with casting away constness of reference
> 'c' since it doesn't actually refer to const object.
>
> Temporaries are mutable, so in whole my snippet is legal C++. Am i correct?


AIUI, your code has undefined behavior. 'c' is bound to an rvalue, and
using 'const_cast' to produce an lvalue out of it is not among the
allowed operations for 'const_cast'.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      11-19-2011
On 11/19/2011 8:18 AM, Paavo Helde wrote:
> kyle<> wrote in
> news:
>
>> Consider following code:
>>
>> int main() {
>> const int& c = int();
>> int& m = const_cast<int&>(c);
>> m = 4;
>> }
>>
>> The object of the snippet is to get a mutable reference to a
>> temporary. This cant be done directly because non-const reference
>> cannot bind to temporary, but we should be OK with casting away
>> constness of reference 'c' since it doesn't actually refer to const
>> object.
>>
>> Temporaries are mutable, so in whole my snippet is legal C++. Am i
>> correct?

>
> Yes, I think you are correct. Another trick to get a mutable reference to
> a temporary is to use a non-const member function. This avoids
> const_cast, but of course lifetime extending by binding to a const
> reference does not work any more:
>
> struct A {
> int m;
> A& Ref() {return *this;}
> };
>
> void f(A& a) {
> a.m = 4;
> }
>
> int main() {
> f( A().Ref() );
> }
>


There is a difference between your example and the OP's. In your
example the temporary is of a class type, and the expression A()
produces an lvalue to begin with.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Johannes Schaub
Guest
Posts: n/a
 
      11-19-2011
kyle wrote:

> Consider following code:
>
> int main() {
> const int& c = int();
> int& m = const_cast<int&>(c);
> m = 4;
> }
>
> The object of the snippet is to get a mutable reference to a temporary.
> This cant be done directly because non-const reference cannot bind to
> temporary, but we should be OK with casting away constness of reference
> 'c' since it doesn't actually refer to const object.
>


The error in your thinking is that you think that "int()" is a temporary
object.

However, "int()" is not a temporary object. It is simply a value, and when
it is an initializer of a reference, a temporary object will be initialized
with that value, and the object will have the type and constness of the
referred type of the reference.

So in your case the reference refers to an object of type "const int" - you
are not allowed to modify it.

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      11-19-2011
On 11/19/2011 9:20 AM, Paavo Helde wrote:
> Victor Bazarov<> wrote in
> news:ja8bo7$88k$:
>
>> On 11/19/2011 7:33 AM, kyle wrote:
>>> Consider following code:
>>>
>>> int main() {
>>> const int& c = int();
>>> int& m = const_cast<int&>(c);
>>> m = 4;
>>> }
>>>
>>> The object of the snippet is to get a mutable reference to a
>>> temporary. This cant be done directly because non-const reference
>>> cannot bind to temporary, but we should be OK with casting away
>>> constness of reference 'c' since it doesn't actually refer to const
>>> object.
>>>
>>> Temporaries are mutable, so in whole my snippet is legal C++. Am i
>>> correct?

>>
>> AIUI, your code has undefined behavior. 'c' is bound to an rvalue,
>> and using 'const_cast' to produce an lvalue out of it is not among the
>> allowed operations for 'const_cast'.

>
> The lvalue and rvalue notions apply to source code expressions (3.10/1:
> "Every expression is either an lvalue or an rvalue"). Expression 'c' is
> of a reference type, which means it is a lvalue, doesn't it? (rvalue
> references use&& syntax). And lvalue->lvalue conversion is well defined
> for const_cast.
>
> Or have I misunderstood something?


int() is an rvalue expression. Now, explain that.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      11-20-2011
On Nov 19, 2:45*pm, Victor Bazarov wrote:

> There is a difference between your example and the OP's. *In your
> example the temporary is of a class type, and the expression A()
> produces an lvalue to begin with.


You seem to confuse two concepts, (1) value category and (2) whether
or not an expression refers to an object. There is some correlation
between these two but no equivalence. What is true though is that
every lvalue (of object type) refers to an object. But T() is always
an rvalue expression no matter what kind of object type T is (scalar
or not). Let me quote part of 3.10 of the current C++ ISO standard:

"An rvalue (...) is an xvalue, a temporary object or a subobject
thereof, or a value that is not associated with an object."

So, saying that A() is an rvalue which refers to a temporary object is
not a contradiction.

In the former version of the standard it was also clarified when an
rvalue (that is not an xvalue) actually refers to an object and when
not. I can't find it in the current incarnation but I guess it did not
change. PRvalues of _scalar_types_ are not associated with an object,
they are just "values". And since int is a scalar type int() does not
refer to an object (temporary or otherwise). But of course, a
reference of object type has to refer to an object. That's why a
temporary object is created as part of the reference initialization
procedure.

I suggest to look up §3.10 and the part about reference initialization
in both versions of the C++ ISO standard.

Cheers!
SG
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      11-21-2011
On Nov 19, 1:33*pm, kyle wrote:
>
> int main() {
> * *const int& c = int();
> * *int& m = const_cast<int&>(c);
> * *m = 4;
> }
>
> [...]
>
> Temporaries are mutable, so in whole my snippet is legal C++. Am i correct?


Yes, I believe so. I would not go as far as saying "temporaries are
mutable" because one can easily create const class-type temporaries.
These are obviously not mutable unless they have mutable data members.
But, I agree with Paavo on this one. As far as I can tell, no
undefined behaviour is invoked here.

Cheers!
SG
 
Reply With Quote
 
Johannes Schaub
Guest
Posts: n/a
 
      11-22-2011
SG wrote:

> On Nov 19, 1:33 pm, kyle wrote:
>>
>> int main() {
>> const int& c = int();
>> int& m = const_cast<int&>(c);
>> m = 4;
>> }
>>
>> [...]
>>
>> Temporaries are mutable, so in whole my snippet is legal C++. Am i
>> correct?

>
> Yes, I believe so. I would not go as far as saying "temporaries are
> mutable" because one can easily create const class-type temporaries.
> These are obviously not mutable unless they have mutable data members.
> But, I agree with Paavo on this one. As far as I can tell, no
> undefined behaviour is invoked here.
>


What do you say about the point I have made about the code?

 
Reply With Quote
 
kyle
Guest
Posts: n/a
 
      11-23-2011
Dnia 19-11-2011 o 16:16:45 Johannes Schaub
<> napisaƂ(a):

> kyle wrote:
>
>> Consider following code:
>>
>> int main() {
>> const int& c = int();
>> int& m = const_cast<int&>(c);
>> m = 4;
>> }
>>

>
> The error in your thinking is that you think that "int()" is a temporary
> object.
>


This is indeed what i assumed.
As i understand, i could 'fix' the code by having a function 'int foo()
{return 1;}' and using it in place of 'int()'?

Unfortunately, what i originally planned to do is illegal for entirely
different reason

--
kyle
 
Reply With Quote
 
Johannes Schaub
Guest
Posts: n/a
 
      11-24-2011
kyle wrote:

> Dnia 19-11-2011 o 16:16:45 Johannes Schaub
> <> napisaƂ(a):
>
>> kyle wrote:
>>
>>> Consider following code:
>>>
>>> int main() {
>>> const int& c = int();
>>> int& m = const_cast<int&>(c);
>>> m = 4;
>>> }
>>>

>>
>> The error in your thinking is that you think that "int()" is a temporary
>> object.
>>

>
> This is indeed what i assumed.
> As i understand, i could 'fix' the code by having a function 'int foo()
> {return 1;}' and using it in place of 'int()'?
>


No, as someone else already said, rvalues of non-class and non-array type
are not objects, and the rules for initialization of references adequately
are worded to take that into account. It will behave exactly like the
"int()" case.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Mutability, copying lists but not sharing? cnb Python 1 08-26-2008 12:56 AM
named tuple mutability castironpi@gmail.com Python 10 05-15-2008 10:43 AM
list mutability gigs Python 1 02-18-2008 07:40 PM
Mutability of function arguments? ex_ottoyuhr Python 17 12-08-2005 05:17 PM
Mutability problem when subclassing tuple Edward C. Jones Python 2 02-19-2004 10:17 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57