Re: Move semantics vs copy elision
On 2 Mai, 21:23, Robi-Wan-Kenobi wrote:
Hello
i read and heared a lot about rvalue references and move semantics in C
++0x.
That sounds cool but one thing puzzles me: Some serious websites like
e.g.http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
come up with the statement that recent compilers are quite
sophisticated in optimizing out a huge amount of unnecessary copies.
So i assume that implementing move constructors and assignment
operators will only result in a performance gain where the compiler
wasn't able to do the optimization on its own.
First of all, no compiler is able to perform all copy elisions that
are allowed by the standard. But G++ is pretty close to that.
Secondly, there are lots of situations where copy elisions are not
allowed but the user explicitly wants a move construction or move
assignment instead of a copy. Example:
template<class T>
void swap(T & a, T & b) {
T tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}
Here, we use std::move to tell the compiler to prefer a move
constructor or move assignment in case T offers them because we don't
need copies here.
Think of a vector<string> and consecutive push_backs. We don't want
the vector to grow by *copying* strings into a new buffer. We want it
to grow by *moving* strings from one buffer to another one with higher
capacity. If std::string offers a fast noexcept move ctor (and it
will) this is going to be much more efficient than copying strings.
I'm a bit afraid that implementing that stuff turns out to be
premature optimization, which is known to be the source of all
evil...
"Implementing that stuff" is not supposed to be a burden. If you feel
the need to write many copy ctors by yourself, you _probably_ did
something wrong. At least in my application domain I almost write no
copy ctors because I can build classes out of smaller components which
already have the correct copy semantics (i.e. vector<T> instead of a
T* member, etc). I think, the same applies to move ctors as well since
move ctors can be generated automatically in certain cases. The
"building blocks" from the standard library (containers, string,
thread, smart pointers, ...) are all going to have move constructors
and you'll be benefiting from it without doing anything special. In
addition, you can manually turn a copy into a move via std::move if
you want to.
So, with move semantics in C++11, you basically get three things:
- if your program relies on some STL building blocks,
it will instantly get faster (to some degree) without
doing anything but switching to C++11 mode.
- you can create and use a new species of types (move-only types)
and store them in standard containers
- you can manually force a move if you don't need a copy and
the type supports it.
In my own code, I used it only once for a copy-on-write wrapper class.
The idea was to keep reference counts low and thus prevent unnecessary
copies. To be honest, I did not measure the benefit, but adding a move
ctor to that class was a matter of a couple of seconds. I guess moving
a std::shared_ptr will also be cheaper than copying it since moving
such a smart pointer does not involve touching the reference counter.
Cheers!
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]