On Thu, Sep 10, 2009 at 5:43 PM, Nasos Iliopoulos <nasos_i@hotmail.com> wrote:
Jesse,

>I don't know that much about this stuff, but my understanding is that rvalue refereces and move semantics allow a library to overload the rvalue assignment to do a this kind of pointer swapping.  But this stuff is probably very difficult to do.


I guess I knew what I was talking about when I suggested I don't know what I am talking about.
 
That's the trick data().swap(..) does, it takes the passed by value data and swaps its pointer with the object calling it <--I can discuss a bit more about that but it may get too technical (i.e. std::swap(..,..) vs container.swap(...) ). Also the compiler should be (in my case is) responsible to take care of the value passed using copy elision. If it is an rvalue it will pass it in without copying; or copy it if it is not - which is what we want.

I did some tests and if the you are interested I can prepare to post them. The memory in those tests certainly shows half memory usage with move semantics for a large vector. Tracing back gives no indication of the existence of two containers and the performance is increased by about 20-30%. Also there is no indication of shallow copy (left and right side containers remain two distinct objects with distinct storage).


Wow... is it really that easy?  I thought the above code would cause all sorts of aliasing disasters...

Is this really good enough to use for functions returning big matrices as return values?

Take the following:
template<typename MatrixT>
matrix<double> inv(const matrix_expression<MatrixT>& A)
{
  matrix<double> B(A().size1(), A().size2());
  //Say a complicated sequence to invert A into B, which can't just return a matrix expression.

return B;
}

vs. a standard one with the return value passed in by non-const reference.
template<typename MatrixT>
void inv(const matrix_expression<MatrixT>& A, matrix<double>& B)
{
  //Complicated sequence to invert A into B, which can't just return a matrix expression.
}

//Now take the client code, for very large matrices.
matrix<double> B = inv(A); //Does the swap method above cause an invalid data pointer due to returning a temporary?

Any overhead in the copy vs. inv(A, B); ?

//Now do it with matrix expressions on both sides...
matrix<double> B = 2 * inv( .5 * A);

Is there any overhead on this vs.:
matrix<double> B(A.size1(), A.size2());
inv(.5 * A, B);
B *= 2;