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's a deleted function
Why does the latter call to the move constructor? Why are these 2 statement different in terms of generated code?
A Level 3 ready autonomous vehicle is capable of driving itself in particular conditions, during which it will take control of all safety-critical systems. In proper circumstances, the ADS (Automated Driving System) completes the entire dynamic driving task and then disengages quickly upon the driver's command.
Having said this, it's worth pointing out that, according to J.D Power, as of May 2021, no vehicles sold in the U.S. market have a Level 3, Level 4, or Level 5 automated driving system. All of them require an alert driver sitting in the driver's seat, ready to take control at any time.
Level 3 systems cannot drive on highways, Level 4 systems can. Level 3 systems only have lateral or longitudinal control, Level 4 systems have both. Level 3 systems retire full user alertness, Level 4 systems do not
auto a = A(3);
means the same as A a = A(3);
since the type of the right hand side is A
.
This means exactly what it looks like: A(3)
creates a temporary A
initialized with 3
, and then A a = _____
means: create an A
called a
with _____
as initializer.
So you create a temporary, pass that to a
as initializer, and then the temporary is destroyed. This type of initialization (with =
) is called copy-initialization (although don't confuse that with "copy", it's just a word).
A constructor is selected to construct a
which accepts an A
. This must be either a copy or a move constructor. A
has a move constructor and a copy constructor. The latter is implicitly-generated and defined as deleted too, because there is a user-declared move constructor.
Being defined as deleted doesn't affect overload resolution though; and the move-constructor is preferred to the copy-constructor in this case.
So your code attempts to call a delete
d function, which is ill-formed, hence the error.
Note that if the move-constructor were not deleted, then copy elision would apply. It kicks in in some circumstances where a variable is initialized from a temporary, or a local variable is returned by value. The rule is that the compiler may use the same memory for both a
and the temporary object, and omit the call to the copy/move constructor.
Most/all compilers would actually do this in the circumstance. So you can actually write auto a = A(3);
and in practice not get any unnecessary moves. If you write some code for your move-constructor that outputs something, you will hopefully find that nothing is output.
If you want to make absolutely sure there is no unnecessary copy, or construct an object that has no usable copy nor move constructor - stop writing code that specifies unnecessary copies! A a(3);
is sufficient.
Why would you expect both code paths to be the same?
You're obviously constructing an unnamed object in the second example, allocating a
(auto a
) and then copying from the temporary to a
(which is a move because we're talking about a temporary object).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With