Resolving if *this is an rvalue (in C++0x)

J

Juha Nieminen

One of the major advantages of rvalue references is that they can be
used to make code more efficient by utilizing the fact that rvalues (eg.
temporaries) can be modified without breaking anything, thus allowing
things like move constructors. One typical situation where this may
come handy is something like this:

Matrix a(1000, 1000), b(1000, 1000); // 1000x1000 unit matrices
Matrix c = a + b;

Matrix::eek:perator+() will obviously have to allocate a new array for
the 1000*1000 elements, where it will put the sum of 'a' and 'b'. But
then when 'c' is constructed from the result, this huge array can
simply be moved to 'c' by its move constructor, which is what rvalue
references enable, thus saving a useless 1000*1000 array allocation
and element copying.

However, imagine we had this instead:

Matrix a(1000, 1000), b(1000, 1000), c(1000, 1000);
Matrix d = a + b + c;

The first "a + b" is the same as before. However, now it would be
beneficial if the result of his, which is an rvalue, could be moved
to the result of the next operator+ (which is called on the temporary,
giving 'c' as parameter).

However, that won't happen because 'c' is not an rvalue, so the
regular operator+() will be called rather than the one taking an rvalue
reference. This will cause a useless allocation and copying of the data.

It would be useful if a member function could somehow deduce that
*this is an rvalue, in which case it knows that it can safely transfer
its own data to the object it's going to return.

However, is there any way of doing that in C++0x?

Of course one could simply define a global operator+() like this, to
achieve the desired outcome:

Matrix operator+(Matrix&& a, const Matrix& b)
{
return a += b;
}

But is there any way of doing it "more properly"? (One could easily
imagine a situation where there's no such operator+= or anything similar
available that could be used for this.)
 
J

Johannes Schaub (litb)

Juha said:
One of the major advantages of rvalue references is that they can be
used to make code more efficient by utilizing the fact that rvalues (eg.
temporaries) can be modified without breaking anything, thus allowing
things like move constructors. One typical situation where this may
come handy is something like this:

Matrix a(1000, 1000), b(1000, 1000); // 1000x1000 unit matrices
Matrix c = a + b;

Matrix::eek:perator+() will obviously have to allocate a new array for
the 1000*1000 elements, where it will put the sum of 'a' and 'b'. But
then when 'c' is constructed from the result, this huge array can
simply be moved to 'c' by its move constructor, which is what rvalue
references enable, thus saving a useless 1000*1000 array allocation
and element copying.

However, imagine we had this instead:

Matrix a(1000, 1000), b(1000, 1000), c(1000, 1000);
Matrix d = a + b + c;

The first "a + b" is the same as before. However, now it would be
beneficial if the result of his, which is an rvalue, could be moved
to the result of the next operator+ (which is called on the temporary,
giving 'c' as parameter).

However, that won't happen because 'c' is not an rvalue, so the
regular operator+() will be called rather than the one taking an rvalue
reference. This will cause a useless allocation and copying of the data.

It would be useful if a member function could somehow deduce that
*this is an rvalue, in which case it knows that it can safely transfer
its own data to the object it's going to return.

However, is there any way of doing that in C++0x?

Of course one could simply define a global operator+() like this, to
achieve the desired outcome:

Matrix operator+(Matrix&& a, const Matrix& b)
{
return a += b;
}

But is there any way of doing it "more properly"? (One could easily
imagine a situation where there's no such operator+= or anything similar
available that could be used for this.)

No need for a global `operator+`. You can, and actually should, define it in
the same namespace that the class Matrix is defined in. Operator functions
can be defined in user defined namespaces.

C++0x allows overloading function based on rvalueness of the implied object
argument:

Matrix operator+(Matrix &&b) && {
/* ... */
}

Allowed is "&&" (for rvalues) and "&" (for lvalues). But this seems to be an
improper way. Defining the operator function in a namespace seems to be the
proper way to me (see Sutter's "What's in a class?").
 
J

Juha Nieminen

Johannes Schaub (litb) said:
C++0x allows overloading function based on rvalueness of the implied object
argument:

Matrix operator+(Matrix &&b) && {
/* ... */
}

Ah, didn't know that. It seems to be exactly what I was thinking about.

(But as you said, it might, at least in some situations, be more proper
to do it with a friend function instead.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top