Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ move constructor called instead of copy constructor

I have this snippet of code which I’m compiling with g++.exe -std=c++20:

#include <iostream>
using namespace std;

class A {
public:
  A() = delete;
  A(int value) : value(value) {}
  // A(auto &other) {
  //   cout << "Copy constructor called..." << endl;
  //   value = other.value;
  // }

  void operator=(const auto &other) = delete;

  A(auto &&other) {
    cout << "Move constructor called..." << endl;
    value = other.value;
  }

  ~A() { cout << "Destructor called..." << endl; }

  friend ostream &operator<<(ostream &os, const A &a);

private:
  int value;
};

ostream &operator<<(ostream &os, const A &a) {
  os << a.value;
  return os;
}

int main() {
  A p1(2);
  cout << "p1: " << p1 << endl;
  A p2(p1);

  cout << "p2: " << p2 << " p1: " << p1 << endl;

  return 0;
}

The problem I’m having is that when the copy constructor is commented the output is

Move constructor called...
p2: 2 p1: 2
Destructor called...
Destructor called...

And if I uncomment the copy constructor, the output becomes

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

p1: 2
Copy constructor called...
p2: 2 p1: 2
Destructor called...
Destructor called...

I am wondering why doesn’t the compiler just call a default copy constructor (what happens when I delete the move constructor or change its argument to const, so it doesn’t match the call).

>Solution :

In this case it’s not actually a move constructor, it’s a constructor with a universal reference, so it takes both lvalues and rvalues. If you want to restrict it to rvalues only, you should use explicit type:

A(A &&other) {
  ...
}

I am wondering why doesn’t the compiler just call a default copy constructor (what happens when I delete the move constructor or change its argument to const, so it doesn’t match the call).

Be advised that this won’t happen, because copy operations are implicitly deleted if you explicitly add any move operation, so you will have to add it explicitly in this case:

A(const A &other) = default;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading