Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am trying to understand C++11 rvalue references and how to use them for optimal performance in my code.

Let's say we have a class A that has a member pointer to a large amount of dynamically allocated data.

Furthermore, a method foo(const A& a) that does something with an object of class A.

I want to prevent the copy constructor of A from being called when an object of A is passed to the function foo, since in that case it will perform a deep copy of the underlying heap data.

I tested passing an lvalue reference:

    A a;
    foo(a);

and passing an rvalue reference:

    foo(A());

In both cases the copy constructor was not called.

Is this expected or is this due to some optimization of my compiler (Apple LLVM 5.1)? Is there any specification about this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
609 views
Welcome To Ask or Share your Answers For Others

1 Answer

That is expected. If you pass an argument to a reference type parameter (whether lvalue or rvalue reference), the object will not be copied. That is the whole point of references.

The confusion you're having is pretty common. The choice of copy or move constructor only occurs when passing an object by value. For example:

void foo(A a);

When passing an A object to this function, the compiler will determine whether to use the copy or move constructor depending on whether the expression you pass is an lvalue or rvalue expression.

On the other hand, none of the following functions would even try to invoke the copy or move constructor because no object is being constructed:

void foo(A& a);
void foo(const A& a);
void foo(A&& a);
void foo(const A&& a);

It's important to note that you should rarely (if ever) have any reason to write a function, other than a move constructor/assignment operator, that takes an rvalue reference. You should be deciding between passing by value and passing by const lvalue reference:

  1. If you're going to need a copy of the object inside the function anyway (perhaps because you want to modify a copy or pass it to another function), take it by value (A). This way, if you're given an lvalue, it'll have to be copied (you can't avoid this), but if you're given an rvalue, it'll be optimally moved into your function.

  2. If you're not going to need a copy of the object, take it by const lvalue reference (const A&). This way, regardless of whether you're given an lvalue or rvalue, no copy will take place. You shouldn't use this when you do need to copy it though, because it prevents you from utilising move semantics.

From the sounds of it, you're not going to make any copies at all, so a const A& parameter would work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...