Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Copy Constructor And Temporary Objects

2 views
Skip to first unread message

Marcelo De Brito

unread,
Mar 1, 2009, 1:00:12 AM3/1/09
to
Hi!

I have stumbled upon an interesting feature when passing objects "by
value" to functions. Let's say I have the following class:

class Class1 {
public:
Class1();
~Class1();
};

And I have two functions that deal with objects from that class:

Class1 func1()
{
Class1 x;
return(x);
}

void func2(Class1& aa)
{
}

So, my objective is passing the return value of "func1" as an argument
to "func2", but doing this directly does not work, that is:

func2(func1()); //!ERROR

BUT, if I define the argument of "func2" as a "const Class1&" type --
that is, "func2(const Class1&)" --, then, no error occurs when calling
"func2(func1())".

Why does that happen?

What is the problem with the line "func2(func1())" ?

Thank You!

Marcelo

Ivan

unread,
Mar 1, 2009, 1:19:14 AM3/1/09
to

Because that function func1 return a temporary object and this object
is a right-value.
Function func2's parameter is Class1 &, a none-const reference. it can
reference any left-value, but can't reference to right-value. Only
const Class1 & type can reference right-value in the readonly
behavior.

In C++0x, the rvalue reference is introduced to address this issue.
You can overload func2 to deal with temporary object as bellow:

void func2(Class1 &&a)
{
...
}

Kai-Uwe Bux

unread,
Mar 1, 2009, 1:21:07 AM3/1/09
to
Marcelo De Brito wrote:

> Hi!
>
> I have stumbled upon an interesting feature when passing objects "by
> value" to functions. Let's say I have the following class:
>
> class Class1 {
> public:
> Class1();
> ~Class1();
> };
>
> And I have two functions that deal with objects from that class:
>
> Class1 func1()
> {
> Class1 x;
> return(x);
> }
>
> void func2(Class1& aa)
> {
> }
>
> So, my objective is passing the return value of "func1" as an argument
> to "func2", but doing this directly does not work, that is:
>
> func2(func1()); //!ERROR
>
> BUT, if I define the argument of "func2" as a "const Class1&" type --
> that is, "func2(const Class1&)" --, then, no error occurs when calling
> "func2(func1())".
>
> Why does that happen?

Because clause [8.3.5/5] of the standard says so.


> What is the problem with the line "func2(func1())" ?

A non-const reference cannot be initialized from a temporary. The argument
to func2 is a non-const reference. A const reference can be initialized
from a temporary. Hence the modified version compiles cleanly.

Comments:

a) One rationale for this provision lies in the implicit conversion rules of
C++. If you had a function

void inc ( int & i ) {
++i;
}

and you would use inc on a parameter of type char, then a temporary of type
int would be created. Now, incrementing that temporary is very likely not
what you want.

b) That temporaries cannot bind to non-const references might create the
impression that temporaries are const. That is not the case: you can call
non-const member functions on temporaries. This leads to some strange
results:

vector< int > iv;
...
vector<int>().swap( iv ); // legal
iv.swap( vector<int>() ); // illegal
swap( iv, vector<int>() ); // illegal

This sometimes presents a trap with streams since some instances of
operator<< are member functions and some are free standing functions.

c) C++0X will have not only have references but also rvalue references,
which obey different rules.


Best

Kai-Uwe Bux

0 new messages