[Development] Setters: Passing by value or const reference?
Olivier Goffart
olivier at woboq.com
Wed Apr 25 14:03:36 CEST 2012
On Wednesday 25 April 2012 13:57:31 Alberto Mardegan wrote:
> Hi Olivier,
>
> On 04/25/2012 01:12 PM, Olivier Goffart wrote:
> > The solution is actually much simpler:
> >
> > void Foo::setText(QString text) {
> >
> > d_ptr->text = std::move(text); // no copy
> >
> > }
> >
> > foo->setText(tr("hello world")); // no copy here, this is a move.
>
> I understand why there wouldn't be a copy in the implementation of
> setText, but why wouldn't calling foo->setText() produce a copy?
> How can the compiler know that it must not create a copy when calling
> Foo::setText(QString text) unless we are inlining it?
Apparently I was not clear enough in my first mail, so more details:
There is two reason why a copy could be avoided:
1) in C++98 already, there is RVO
[http://en.wikipedia.org/wiki/Return_value_optimization]
which allows the compiler to use the return value of a function directly
without making any copies. But RVO is not always possible.
2) in C++11, we have the move sementics. the return value of tr() would be a
temporary (which is of the type QString&&, a rvalue reference) so the
really fast move constructor QString(QString &&) would be called instead
of the copy constructor QString(const QString &)
It was also mentioned to me that my benchmark was biased because setText was
inline. Making it non inline does not make much difference.
But my benchmark did not represent the C++98 slowness as the RVO was applied.
So I did a new benchmark: http://paste.kde.org/463388/
My analysis of the results of that benchmark:
- The cost of a copy is more about 25% the cost of QString::fromLatin1("a");
- in C++11 there is one copy less when the argument of the getter is a
temporary
- in C++98 there is one copy more when the RVO do not apply.
More information about the Development
mailing list