What is the difference between auto a = A (3) and A a (3)?

Suppose I have:

struct A { A(int x) : m_x(x) { } A(A&&) = delete; int m_x; } 

and

 A a(3); // Ok auto a = A(3); // Error: function A(int&&) cannot be referenced - it a deleted function 

Why does the latter call the move constructor? Why are these 2 expressions different in terms of the generated code?

+5
source share
3 answers

Why do you expect both code paths to be the same?

Obviously, you built an unnamed object in the second example, highlighting a ( auto a ) and then copying it from temporary to a (this is movement because we are talking about a temporary object).

+4
source

auto a = A(3); means the same as A a = A(3); , since the type of the right side is A

This means that it looks like this: A(3) creates a temporary A initialized with 3 , and then A a = _____ means: create an A named A with _____ as an initializer.

So, you create a temporary, go to A as an initializer, and then the temporary is destroyed. This type of initialization (c = ) is called copy-initialization (although don't confuse this with “copy”, it's just a word).

The constructor is chosen to build A , which takes A It must be either an instance or a move constructor. A has a move constructor and copy constructor. The latter is implicitly generated and defined as remote, since there is a movement designer declared by the user.

Defined as remote, but does not affect overload resolution; and in this case, the move constructor is preferable to the copy-constructor.

Thus, your code is trying to call the delete d function, which is poorly formed, hence the error.

Note that if the move constructor has not been deleted, then a copy of elision will be applied. It starts in some cases when a variable is initialized from a temporary or a local variable is returned by a value. The rule is that the compiler can use the same memory for both A and a temporary object, and omit the copy / move constructor call.

Most / all compilers will actually do this in this case. So you can write auto a = A(3); and in practice, do not get extra moves. If you write code for your move constructor that outputs something, you hopefully find that nothing is output.

If you want to absolutely make sure that there is no unnecessary copy or to create an object that does not have a usable copy and not to move the constructor, stop writing code that indicates unnecessary copies! A a(3); .

+6
source

It does not matter that the compiler will generate the same code in both cases, because during compilation it is necessary to determine the necessary functions / constructors. Think of it this way: optimization will happen after compiling / parsing the code, but in the end the code will (should be) in this case.

-1
source

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


All Articles