|
Boost : |
From: Andrei Alexandrescu (andrewalex_at_[hidden])
Date: 2002-10-10 16:59:46
I just submitted the message below to clc++m and csc++. I will spam the
boost newsgroup as well for two reasons. One is that there has been heavy
discussion on the topic of move constructors here, and I believe there is a
solution. The second is that the ZUTO (see below, sorry for the forward
declaration :o)) infrastructure is a very good candidate for boost addition.
-------------------------
Hello,
This is a request for a favor.
I believe I have hacked together a complete solution for eliminating
unnecessary temporary objects in C++. The topic relates to the heavy
discussions on move constructors, too. The solution (let's call it ZUTO
(Zero Unnecessary Temporary Objects) henceforth) has the following
characteristics:
1. It does not require language changes.
2. Has no or minimal impact on client code. In many cases, elimination of
many temporary objects is achieved by changing the offending class
definition and recompiling client code. To /totally/ eliminate temporary
objects (and I mean /totally/), client code has only to perform a minor
change when returning lvalues from functions.
3. Lends itself to a library implementation accompanied by simple idioms.
4. Is guaranteed, i.e., you're not at the mercy of a fragile RVO (Return
Value Optimization) implementation which might or might not kick in.
5. Works in all cases, whereas RVO works only in certain cases.
6. Does not require ugly client syntax nor ugly class definition syntax.
(Your mileage might vary for the latter.)
7. Does not do advanced temporary elimination a la loop fusion, which is
solved by using expression templates. (Fortunately, ZUTO is at least much
simpler than expression templates.) So it could be said ZUTO does eliminate
all unnecessary temporaries, for a reasonable definition of "unnecessary"
:o).
8. ZUTO is likely to be supported by all compilers that know enough to
compile std::auto_ptr.
We all are aware of the nuisance that unnecessary temporary objects are. We
are afraid to write elegant code such as:
extern vector<string> Fun();
...
vector<string> v = Fun();
because we know a temporary might be created, which might pretty much ruin
the performance of the application. Even if we could count on a compiler
implementing RVO (which is not guaranteed nor implemented everywhere nor
supported in similar forms on most compilers), the following is /guaranteed/
to create an unnecessary temporary, even though there's no need for it:
extern vector<string> Fun();
...
vector<string> v;
...
v = Fun();
To get rid of that, we have to recourse to the damned hack:
Fun().swap(v);
Furthermore, when passing Fun's result to some function, again an
unnecessary temporary can be created. And so on.
The hack I'm telling about solves all the problems above in a manner that I
believe is elegant enough to deserve attention. I will first talk about it
at The C++ Seminar (see my sig). The implications in C++ idioms, class
design, coding standards, and maybe even compiler design, are possibly quite
deep. Here are some examples:
* One can now design an auto_ptr that does what auto_ptr is designed to do,
but without any of its horrible caveats. In particular, the newly-designed
auto_ptr can be safely stored in certain containers. Any wrongful use will
be flagged at compile time.
* The recommended conventions for passing values to and returning values
from functions might change forever.
* Here are current state-of-the-art recommended canonic signatures and
implementations of some primitive functions:
class T
{
...
T& operator=(const T& rhs)
{
T copy(rhs);
rhs.swap(*this);
return *this;
}
};
const T operator+(const T& lhs, const T& rhs)
{
T copy(lhs);
return copy += rhs;
}
I reached the conclusion that the signatures and implementations above are
about the worst possible to recommend, with or without ZUTO in action. I
consider them simply wrong.
I tested ZUTO on MSVC.NET Everett Beta and MWCW 7.0, and it screams. It's a
pleasure to run through the debugger and see the temporaries disciplinately
flowing from source to destination without any efficiency hitch.
Exactly because the implications might be so deep, I don't want to make a
fool of myself. Maybe I am making some mistake, or I overlooked something,
or I hit onto some compiler bug or extension. So I wanted to ask for some
volunteers to review my article before it goes out. If there are volunteers,
please write me email. The article will be out in 2 months, and I believe
I'll have something done in a couple of weeks.
Andrei
-- All new! THE C++ Seminar: Oct. 28-30 in Vancouver, WA. http://www.thecppseminar.com/
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk