1

"Beginner to C++"

Why do so many classes use =default for the copy constructor and assignment operator and on their non-virtual destructors?

How is

class A{
public:
    A() = default;
    A(int);
};

different from

class A{
public:
    A() = default;
    A(int);
    A(const A&) = default;
    A& operator=(const A&) = default;
    ~A() = default;
};

My understanding is that even without these =default, these operations will be synthesized.

MSS
  • 553
  • 2
  • 11
  • 1
    In the simple examples you show, they should all be generated automatically. But there are many cases where one or more will *not* be declared or defined automatically and then `= default` is useful. – Some programmer dude Dec 07 '18 at 11:37
  • My understanding is that if it is not synthesized, then it is because there is a member in the class which cannot be copied or assigned to. So in that case using =default would give an error right. It is because of that I am confused as to why this is required. – MSS Dec 07 '18 at 11:39
  • 1
    Actually the rules are [quite complex](https://stackoverflow.com/questions/4943958/conditions-for-automatic-generation-of-default-copy-move-ctor-and-copy-move-assi) and special functions that would be fine can still be disabled. Thus many developers prefer being explicit and just request default or deleted functions manually. – Quentin Dec 07 '18 at 11:40
  • I have no idea what move constructors and move assignment is. Guess i will have to go back to the drawing board then. – MSS Dec 07 '18 at 11:43

1 Answers1

3

Even when the methods can be generated automatically, explicitly declaring them enables

  • control of visibility (private, protected, public)
  • adding documentation comments
  • demonstrating that the author hasn't forgotten to mark them =delete
  • ensuring that adding a non-copyable member will cause a clear and understandable failure as early as possible
  • disabling move operations (though that's better done with =delete on the relevant members instead)

Sometimes members need to be declared in the header, and implemented with =default in the implementation, if the class has a member of incomplete type which must be copied or deleted. This is quite common for destructors when implementing the PIMPL pattern using a const std::unique_ptr<impl>.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • I'd say earlier failure -- although *some* compilers are absolutely garbage at reporting errors from defaulted member functions so that's not a given. – Quentin Dec 07 '18 at 11:45
  • Not necessarily just earlier. There may be no failure at all if your current uses don't require the copy operations, but you may still want to be sure that future uses aren't prevented. And you certainly don't want to be shipping a library class that unexpectedly breaks copying (although one would hope that your unit tests would exercise that!). – Toby Speight Dec 07 '18 at 11:50
  • 1
    We're agreeing here -- finding the bug after the library has shipped would just be terribly late ;) – Quentin Dec 07 '18 at 11:51