move, instead of copy, assignment

Discussion in 'C++' started by Jonathan Lee, Aug 11, 2009.

  1. Jonathan Lee

    Jonathan Lee Guest

    Hi all,
    I was wondering if there is a good way to detect an assignment from
    an anonymous variable, so that the assignment might be accomplished by
    a move, instead of a copy. For example:

    MatrixClass x, y, z
    // stuff happens to x, y, and z
    // ...
    z = x + y;

    Suppose MatrixClass keeps a pointer to its data, which will be deleted
    on destruction. Rather than copy (x + y) to z, it would be cheaper to
    simply exchange the pointers inside the classes and allow the old z
    data be deleted when (x + y) is destroyed.

    Can such a thing be done automatically? Or would I have to use
    something like

    swap(z, x + y);

    instead?

    --Jonathan
    Jonathan Lee, Aug 11, 2009
    #1
    1. Advertising

  2. Jonathan Lee

    Jonathan Lee Guest

    On Aug 10, 8:06 pm, Jonathan Lee <> wrote:
    > Hi all,
    >   I was wondering if there is a good way to detect an assignment from
    > an anonymous variable, so that the assignment might be accomplished by
    > a move, instead of a copy. For example:


    K. Just minutes after posting this I discovered "rvalue references"
    and "move semantics", for C++0x. And apparently, a template
    specialization of std::swap is the agreed upon way of doing this
    currently.

    --Jonathan
    Jonathan Lee, Aug 11, 2009
    #2
    1. Advertising

  3. * Jonathan Lee:
    > On Aug 10, 8:06 pm, Jonathan Lee <> wrote:
    >> Hi all,
    >> I was wondering if there is a good way to detect an assignment from
    >> an anonymous variable, so that the assignment might be accomplished by
    >> a move, instead of a copy. For example:

    >
    > K. Just minutes after posting this I discovered "rvalue references"
    > and "move semantics", for C++0x.


    You'd need a compiler that supports that, though.


    > And apparently, a template
    > specialization of std::swap is the agreed upon way of doing this
    > currently.


    Huh?

    But anyway, within C++98 you can always try out Andrei's old Mojo library.

    See article in DDJ.

    However, there's no free lunch.

    Mojo, as I recall, had a detrimental effect on some compilers' optimization.


    Cheers & hth.,

    - Alf
    Alf P. Steinbach, Aug 11, 2009
    #3
  4. Jonathan Lee

    Jonathan Lee Guest

    On Aug 10, 8:51 pm, "Alf P. Steinbach" <> wrote:
    > * Jonathan Lee:
    > > And apparently, a template specialization of std::swap is the
    > > agreed upon way of doing this currently.

    > Huh?


    I mean that a swap would effectively do what I want. And, as inelegant
    as it is, the notation is common enough so that if someone were
    reading
    my code they wouldn't think "What the hell is this?"

    > But anyway, within C++98 you can always try out Andrei's old Mojo library..


    Thanks, Alf. I'll take a look.

    --Jonathan
    Jonathan Lee, Aug 11, 2009
    #4
  5. Hi!

    Jonathan Lee wrote:
    > I was wondering if there is a good way to detect an assignment from
    > an anonymous variable, so that the assignment might be accomplished by
    > a move, instead of a copy. For example:
    >
    > MatrixClass x, y, z
    > // stuff happens to x, y, and z
    > // ...
    > z = x + y;


    You might think about reference type semantics for such complex objects.
    I.e. different MatrixClass instances might refer to the same storage.

    Firstly you could make the objects immutable. This is useful if
    reassignments or changes typically require reallocation anyway.
    (example: strings). If the objects are immutable you do not have to take
    care of unexpected value changes because of the references.

    But if the dimensions of your MatrixClass are likely not to change but
    only the values change then immutable objects will cause far too many
    reallocations. In this case you could use copy on write semantics. That
    means that the matrix class firstly checks whether the reference counter
    is 1, i.e. the storage is already private before it makes any changes to
    the storage. Otherwise the assignment (or change) is made to new storage.

    The disadvantage of the reference counting is that you typically have to
    deal with threading issues. If normal thread safety satisfy your needs
    (I.e. no threads copies MatrixClass instances that can asynchronously
    change without a mutex. - I guess that is OK.), then a lock free
    implementations is your choice. boost::intrusive_ptr should satisfy your
    needs for the holder of the matrix storage.

    > Suppose MatrixClass keeps a pointer to its data, which will be deleted
    > on destruction. Rather than copy (x + y) to z, it would be cheaper to
    > simply exchange the pointers inside the classes and allow the old z
    > data be deleted when (x + y) is destroyed.


    This is a common way, but it requires changes to the application code
    rather then only changes to the library.
    Also, if you want to benefit from in-place operations changes to the
    application code are required. Example: assuming that not only x+y but
    also x and y are temporary values you could write:

    z.swap(x) += y;

    which obviously does not require any additional allocation. But, the
    readability is limited.

    Another idea could use a proxy type for the rvalues of operator which
    behaves different on assignment and copy construction. I don't know
    about C++0x but the move semantics mentioned sounds similar.


    Marcel
    Marcel Müller, Aug 11, 2009
    #5
  6. Jonathan Lee

    SG Guest

    On 11 Aug., 02:06, Jonathan Lee <> wrote:
    >   I was wondering if there is a good way to detect an assignment from
    > an anonymous variable, so that the assignment might be accomplished by
    > a move, instead of a copy. For example:
    >
    >       MatrixClass x, y, z
    >       // stuff happens to x, y, and z
    >       // ...
    >       z = x + y;
    >
    > Suppose MatrixClass keeps a pointer to its data, which will be deleted
    > on destruction. Rather than copy (x + y) to z, it would be cheaper to
    > simply exchange the pointers inside the classes and allow the old z
    > data be deleted when (x + y) is destroyed.


    Yes, this is what you will be able to do with a "move assignment
    operator" in C++0x:

    class MatrixClass
    {
    std::vector<double> elements;
    ...
    // copy assignment operator
    MatrixClass& operator=(MatrixClass const& x) & = default;

    // move assignment operator
    MatrixClass& operator=(MatrixClass && x) &
    {
    this->clear();
    this->swap(x);
    return *this;
    }
    ...
    };

    [Actually, I'm not sure whether the ref qualifier is legal in
    combination with the =default; syntax. I hope that it is.]

    Still, if operator+ returns a MatrixClass Objekt memory is allocated
    (for the temporary object) and other memory is released again (after
    swapping with the target object).

    You could probably do even better with "expression templates" where
    operator+ returns a "lazy matrix" that doesn't require a memory
    allocation. The matrix class could have an additional assignment
    operator that takes this "matrix expression" object and actually
    evaluates it and stores the result directly. You can do this with C+
    +98 already and I think this is what Boost.uBLAS does already.

    Cheers!
    SG
    SG, Aug 11, 2009
    #6
    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. Alex
    Replies:
    2
    Views:
    1,193
  2. Replies:
    26
    Views:
    2,074
    Roland Pibinger
    Sep 1, 2006
  3. Eduardo78
    Replies:
    0
    Views:
    233
    Eduardo78
    Nov 3, 2005
  4. Andrew Tomazos
    Replies:
    2
    Views:
    578
    Nobody
    Dec 12, 2011
  5. Mounir
    Replies:
    13
    Views:
    162
Loading...

Share This Page