Need of explicit copy constructor if virtual destructor defined

151 Views Asked by At

After update, my Visual Studio compiler started producing "warning C5267: definition of implicit assignment operator for 'Value' is deprecated because it has a user-provided destructor" with the following simple classes defined:

class Value {
public:
  virtual ~Value() = default;
  virtual void print() = 0;
};

class IntValue : public Value {
  int val;
public:
  IntValue(int val_) : val(val_) { }
  virtual void print() override;
};

// class StrValue : public Value { ... }

// Typical usage, what is needed (added on 12/12/2023)
std::vector<std::unique_ptr<Value>> values;
values.emplace_back(std::make_unique<IntValue>(15));

IntValue a, b;
a = b;  // warning
IntValue c(a);  // warning

Documentation refers to Annex D.8 https://eel.is/c++draft/depr.impldec#1 which explains that if there is a "user declared destructor", the generation of "implicit copy assignment" is deprecated. Similarly for implicit copy constructor (https://eel.is/c++draft/class.copy.ctor#6).

Questions: 1. Do I correctly understand that, if I don't want to use deprecated feature, I need to add explicit copy constructor and copy assignment? 2. What to do with move constructor and move assignment? 3. I frequently add virtual destructor to ensure correct destruction through the base class reference. Does it really mean that I generally need to add all these functions below in this case?

class Value {
public:
  virtual ~Value() = default;

  Value(Value const &) = default;  // implicit decl deprecated because of destructor
  Value(Value &&) = default;  // need to add if I need optimized move (if Value had "big attributes)?
  Value &operator=(Value const &) = default;  // implicit decl deprecated becase of destructor
  Value &operator=(Value &&) = default;  // dtto - needed for optimized move assign?
  Value() = default;  // implicit default constr disabled by explicit copy constr above

  virtual void print() = 0;
};

It looks for me as a domino effect and adding just a virtual destructor (which is, per my understanding, quite common) "requires" so much useless code.

0

There are 0 best solutions below