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

struct/class return by value and assignment

0 views
Skip to first unread message

Daniel

unread,
Nov 23, 2009, 10:02:09 PM11/23/09
to
So why does the following compile? (g++ and comeau)
struct F{
int i;
};
F f() { return F();}
void function() {
f()=F();
}

If I replace F with int (or return a pointer pointer), the compiler
gives the expected message that the return of f() is not an l-value.
But it compiles fine as above (just produces unexpected results). This
came up with a class which has operator[] which returns by value and
allowed c[10]=value; to compile, but have no actual effects. I guess
the right solution is to return a "F const" (in generic code, so it
works with pointers too) or a const &.

Should such compile? And why is a builtin type different from a struct
in this context? Thanks.
--Daniel

James Kanze

unread,
Nov 24, 2009, 4:53:58 AM11/24/09
to
On Nov 24, 3:02 am, Daniel <drus...@gmail.com> wrote:
> So why does the following compile? (g++ and comeau)
> struct F{
> int i;};

> F f() { return F();}
> void function() {
> f()=F();
> }

The simple, usless answer is: because the standard requires it.

> If I replace F with int (or return a pointer pointer), the
> compiler gives the expected message that the return of f() is
> not an l-value. But it compiles fine as above (just produces
> unexpected results). This came up with a class which has
> operator[] which returns by value and allowed c[10]=value; to
> compile, but have no actual effects. I guess the right
> solution is to return a "F const" (in generic code, so it
> works with pointers too) or a const &.

> Should such compile? And why is a builtin type different from
> a struct in this context?

The reason struct is different from other types in this context
is because assignment isn't a built-in operator, but rather an
overloaded operator, and an overloaded operator is a function,
and obeys the rules for functions, and not the rules for the
original operator. Thus, in this case, the rules for the built
in assignment require that the left hand operand be an lvalue,
i.e. not a temporary, but the rules allow you to call a member
function on a temporary. Your line is exactly the same as if
you'd written:
f().operator=(F());

Note that this is true whether or not you explicitly declare an
assignment operator. If you don't declare one, the compiler
declares one for you, but it is still an implicitly declared
function, and *not* the built-in assignment operator.

--
James Kanze

Daniel Pitts

unread,
Nov 24, 2009, 1:17:17 PM11/24/09
to
My guess is a default assignment operator is defined, so f() returns a
temporary, and then operator=(const F &) is invoked on that temporary
with the temporary you constructed with your second F();


Michael Tsang

unread,
Nov 27, 2009, 5:36:22 AM11/27/09
to
Daniel wrote:

You can prevent assignment to r-values by passing *this as a l-value
reference:

struct F {
int i;
F &operator=(const F &x) & { // prevent calling from r-value, not sure if
this can be defaulted
i = x.i;
}
};

White Wolf

unread,
Nov 27, 2009, 11:00:49 AM11/27/09
to

I am unaware of such syntax in the current standard C++ language. Where
did it come from?

--
BR, WW

0 new messages