Home > database >  C move constructor called instead of copy constructor
C move constructor called instead of copy constructor

Time:11-21

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

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).

CodePudding user response:

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;
  • Related