Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic variable initialization and copy/move constructor

Tags:

c++

c++11

auto

I have a snippet:

struct MyCass2 {
  MyCass2() {}

  MyCass2(MyCass2 const&) = delete;

  MyCass2(MyCass2&&) = delete;
};

int
main() {
  auto a = MyCass2();
}

This results in

main.cpp:43:8: error: call to deleted constructor of 'MyCass2'
  auto a = MyCass2();
       ^   ~~~~~~~~~
main.cpp:38:3: note: 'MyCass2' has been explicitly marked deleted here
  MyCass2(MyCass2&&) = delete;
  ^
1 error generated.

Why I thought there will be a template type deduction and a direct initialization after all? Can somebody explain how the automatic variable initialization work in this case?

like image 221
user14416 Avatar asked Sep 19 '26 10:09

user14416


2 Answers

Why I thought there will be a template type deduction

auto uses the rules of template argument deduction to deduce the type of the variable. In this case, the type will be deduced to be MyCass2.

and a direct initialization after all?

a is not direct-initialized, because you used copy-initialization - see the syntax labeled (1).

how the automatic variable initialization work in this case?

a is copy-initialized from the temporary on the right hand side of =. However, since the type is neither copyable, nor movable, the copy initialization is not allowed.

But I [defined] the move/copy constructors and neither of them was called, how is that?

The default constructor was used to initialize the temporary. The call to the move constructor in the copy initialization is allowed to be elided.

I was sure that this auto var=initializer is kind of a syntax overloading. Like with copy initialization T var=initializer, where instead of operator= a copy constructor is called.

Well, it isn't. Here, auto is used for, and only for deducing the type. Once the type has been deduced, the expression is entirely equivalent to

MyCass2 a = MyCass2();
like image 110
eerorika Avatar answered Sep 22 '26 01:09

eerorika


auto a = MyCass2();

Uses copy/move initialization. Now since you have a have a move constructor declared (yes a deleted function is still a declared function) the compiler going to try and use that to move the temporary into a as it is the best match. When it goes to do that though it tries to use the deleted move constructor. Trying to use a deleted function is ill formed and the compiler generates an error.

If you want to allow the above code you work you need to have either the copy or move constructor defined. Do note that in a case like

auto a = some_named_myclass2_object;

The copy constructor needs to be defined as some_named_myclass2_object is an lvalue and cannot be moved from without std::move

like image 31
NathanOliver Avatar answered Sep 22 '26 00:09

NathanOliver



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!