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

Discussion in 'C++' started by Juha Nieminen, Oct 18, 2010.

  1. 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.)
     
    Juha Nieminen, Oct 18, 2010
    #1
    1. Advertising

  2. Juha Nieminen wrote:

    > 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?").
     
    Johannes Schaub (litb), Oct 18, 2010
    #2
    1. Advertising

  3. "Johannes Schaub (litb)" <> wrote:
    > 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.)
     
    Juha Nieminen, Oct 18, 2010
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Mantoulidis

    ++x returns lvalue but x++ return rvalue

    Chris Mantoulidis, Dec 28, 2003, in forum: C++
    Replies:
    4
    Views:
    504
    Chris Mantoulidis
    Dec 29, 2003
  2. Gonzalo Aguirre

    rvalue / lvalue operator[]

    Gonzalo Aguirre, Jan 2, 2004, in forum: C++
    Replies:
    4
    Views:
    456
    Ron Natalie
    Jan 2, 2004
  3. Denis Remezov

    lvalue rvalue

    Denis Remezov, Jul 16, 2004, in forum: C++
    Replies:
    12
    Views:
    880
  4. Kavya
    Replies:
    9
    Views:
    525
    Dik T. Winter
    Oct 28, 2006
  5. Juha Nieminen
    Replies:
    13
    Views:
    636
    Edek Pienkowski
    Aug 29, 2012
Loading...

Share This Page