[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