The difference in efficiency between the copy and move constructor

C ++ 11 introduced the new rvalue link concept. I read it somewhere and found the following:

class Base { public: Base() //Default Ctor Base(int t) //Parameterized Ctor Base(const Base& b) //Copy Ctor Base(Base&& b) //Move Ctor }; void foo(Base b) //Function 1 {} void foo(Base& b) //Function 2 {} int main() { Base b(10); foo(b); -- Line 1 (i know of ambiquity but lets ignore for understanding purpose) foo(Base()); -- Line 2 foo(2) ; -- Line 3 } 

Now, with my limited understanding, my observations are as follows:

  • Line 1 will simply invoke the copy constructor, since the argument is an lvalue.

  • Line 2 before C ++ 11 would name the copy constructor and all these temporary instances, but with a specific move constructor to be called here.

  • Line 3 will again call the move constructor, since 2 will be implicitly converted to the Base (rvalue) type.

Please correct and explain if any of the above observations have occurred.

Now, here are my questions:

  • I know, as soon as we move the object, the data will be lost when called. So, I am above the example, how can I change line 2 to move the object "b" to foo (is std :: move (b) used?).

  • I read the move constructor more efficiently than the copy constructor. How? I can only think about the situation when we have memory on the heap, there is no need to allocate again in the case of moving the constructor. Does this statement mean when we have no memory on the heap?

  • Is it even more efficient than passing by reference (no, right?)?

+6
source share
2 answers

First, about your "understandings":

As far as I understand, they are right in principle, but you should remember that Copy elision can prevent the program from invoking any copy / move constructor. Depends on your compiler (-settings).

To your questions:

  1. Yes, you have to call foo (std :: move (b)) to call a function that takes a value with an lvalue value. std :: move will execute the cast. Note: std :: move itself does not move anything.

  2. Using the Move-Constructor "may" be more efficient. In truth, this only allows programmers to implement more efficient constructors. As an example, consider a vector that is a class around a pointer to an array that contains data (similar to std :: vector), if you copy it, you must copy the data, if you move it, you can just pass the pointer and set the old to nullptr . But, as I read in Scott Meyers’s book, Effective Modern, C ++ : don’t think that your program will be faster just because you always use std :: move.

  3. It depends on the use of input. If you do not need a copy in the function, in most cases it will be more efficient to simply pass the object via a (const) link. If you need a copy, there are several ways to do this, for example, the idiom of copying and sharing . But how

+8
source

Line 2 before C ++ 11 would name the copy constructor and all these temporary instances, but with a specific move constructor to be called here.

That's right, except that any worthy optimizer will "free" a copy, so that before C ++ 11 it could have been avoided, and a C ++ 11 post could have been avoided. Same thing for line 3.


  • I know, as soon as we move an object whose data will be lost when called.

Depends on how the constructor / move destination is implemented. If you do not know, this is what you should accept.

So, I am above an example of how to change line 2 to move object "b" to foo (is std :: move (b) used?).

That's right. std::move changes the type of the expression to r-value, and therefore the move constructor is called.

I read the move constructor more efficiently than the copy constructor.

This may be, in some cases. For example, the std::vector move constructor is much faster than a copy.

I can only think of a situation where we have memory on the heap, there is no need to allocate again in the case of the move constructor. Does this statement mean when we have no memory on the heap?

The statement is not universal, because for objects with a trivial copy constructor, the move constructor is not more efficient. But owning dynamic memory is not strictly a requirement for more efficient movement. In general, a move can be effective if the object owns any external resource, which can be dynamic memory, or it can be, for example, a reference counter or a file descriptor to be released in the destructor and, therefore, designed for a copy - which can be avoided when moving.

Is it even more efficient than passing by reference (no, right?)?

Really no. However, if you intend to transfer the object inside the function where you pass it by reference, you will need to pass a non-constant link and, therefore, will not be able to transfer temporary files.

In short: the link is great for temporarily accessing the object you are storing; moving is great for granting ownership.

+3
source

Source: https://habr.com/ru/post/1261028/


All Articles