Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   move, instead of copy, assignment (http://www.velocityreviews.com/forums/t694334-move-instead-of-copy-assignment.html)

Jonathan Lee 08-11-2009 12:06 AM

move, instead of copy, assignment
 
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 08-11-2009 12:34 AM

Re: move, instead of copy, assignment
 
On Aug 10, 8:06*pm, Jonathan Lee <cho...@shaw.ca> 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

Alf P. Steinbach 08-11-2009 12:51 AM

Re: move, instead of copy, assignment
 
* Jonathan Lee:
> On Aug 10, 8:06 pm, Jonathan Lee <cho...@shaw.ca> 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

Jonathan Lee 08-11-2009 01:12 AM

Re: move, instead of copy, assignment
 
On Aug 10, 8:51*pm, "Alf P. Steinbach" <al...@start.no> 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

Marcel Müller 08-11-2009 08:03 AM

Re: move, instead of copy, assignment
 
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

SG 08-11-2009 05:36 PM

Re: move, instead of copy, assignment
 
On 11 Aug., 02:06, Jonathan Lee <cho...@shaw.ca> 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


All times are GMT. The time now is 06:00 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.