Boost logo

Boost :

From: Pavel Chikulaev (pavel_chikulaev_at_[hidden])
Date: 2005-03-03 18:04:19


Hi,

Do you know that well-known Herb Sutter's assignment operator in most cases
does unnecessary copying? No? Then read it to learn how to elminate it.

class Matrix
{
    //....
    Matrix& operator = (const Matrix& that)
    {
        Matrixtemp(that);
        swap(temp);
        return *this;
    }
    //...
};

Consider first example:
Matrixa, b;
//....
a = b;

Here Herb Sutter's operator = works just fine. But consider second example:

Matrix func ();
Matrix a;
//...
Matrix = func();

Result of func() is copied to temporary objectand then operator = copies it
again. So assigning to result of function creates one useless object.

Elminating of temporary int object will cost nothing, but elminating of
temporary std::vector of 10000 elements will cost a lot.

But how can we define that copying is necessary? - Every function returns
object not of type T but temporary object of type T. So let's code
something:

template<typename T>
struct temporary : T
{
    temporary() {}
    temporary(const T & t) : T(t) {}

    //some operators and constructors to create base object in-place not
listed here
};

Now let's change function consider operator +:

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

To optimize it we do the following:

temporary<Matrix> operator + (const Matrix & a, const Matrix & b)
{
    Matrix temp(a);
    temp += b;
    return temp;
}

Maybe it can be hardly optimized using NRVO, so let's help the complier
rewriting as following:

temporary<Matrix> operator + (const Matrix & a, const Matrix & b)
{
    temporary<Matrix> temp(a);
    temp += b;
    return temp;
}

By now, even returning temporary<Matrix> instead of Matrix, no optimization
is done.
To enable the optimization we need to change the class Matrix by adding one
more assignment operator :

Matrix & operator = (const temporary<Matrix> & that)
{
    swap (const_cast<Matrix &>(static_cast<const Matrix &>(that)));
    return *this;
}

or using "deprecated" casts

Matrix & operator = (const temporary<Matrix> & that)
{
    swap ((Matrix &) that);
    return *this;
}

By now we've elminated unnecassary copying.

Is this worth being called Pavel Chikulaev's temporary assignment operator?
Is this worth being included in Boost?

By including temporary.hpp, adding one operator in class, and replacing each
function result to explicitly marked temporary you get really a lot.

My temporary assignment operator as safe as Herb Sutter's.

Maybe returing temporary<T> will make some obstacles to templated
programming, so i'm going to add temporary_traits: is_temporary,
add_temporary, remove_temporary. Some changes of BOOST_TYPEOF will be also
needed.

So, what do you think?

Copyright 2005 Pavel Chikulaev. Use, modification, and distribution are
subject to the Boost Software License, Version 1.0


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk