18

I read this question, but it still doesn't make a lot of sense to me. It still sounds more like a sugarcoating feature.

What's the difference between:

class A 
{
// public/private ?
    A (const A&) = delete; 
};

and

class A 
{
private:
    A (const A&); // MISSING implementation
};

Same for operator= or other functions.

Community
  • 1
  • 1
Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
  • 2
    Making them `private` doesn't stop you (the class implementor) calling them accidentally. – Simple Sep 17 '13 at 10:59
  • 1
    @Simple - the executable will not be built if you try to call it.. – Kiril Kirov Sep 17 '13 at 11:00
  • I believe that's technically an ill-formed program with no diagnostic required. You will also get a linker error rather than a compiler error. – Simple Sep 17 '13 at 11:02
  • @Simple - yes, you'll get a linker problem, so it will be caught while building the project/program. It's safe, the function will NOT be actually called/executed. – Kiril Kirov Sep 17 '13 at 11:03
  • 7
    @KirilKirov: it is not (necessarily) safe when building DLLs, because you have plenty of missing symbols in DLLs and only when you load them will you realize if one is (still) missing; and thus the error is caught **at runtime** in those cases. – Matthieu M. Sep 17 '13 at 11:28
  • @MatthieuM. - right, good point. I didn't think about that. – Kiril Kirov Sep 17 '13 at 11:58
  • @MatthieuM. I would rather not expect this for Win32 DLLs, as opposed to Posix SOs. – ach Aug 24 '22 at 07:01

4 Answers4

23

One difference is that =delete allows for compile-time errors while in some cases the declaration without a definition is only caught at link-time (at which the error message is typically not pointing you to the source of the problem). One such case is when you add a member function that tries to copy an instance of A. Even when it's not a member function of A, the error message about the copy-ctor being private is not as clear as using =delete.

To avoid confusion, I'd recommend you make the deleted function public as otherwise you will get additional and misleading error messages.

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
  • I'll accept this answer, as it clearly "highlights" compile/link time, **BUT** I'd like to add here, that without the `delete` modifier, the error can be caught event **AT RUNTIME** - see the comment below the question by @MatthieuM. – Kiril Kirov Sep 18 '13 at 10:49
  • @KirilKirov You then might consider distinguishing between load-time and run-time. Most of the problems when using DLLs/shared libraries will arise at load-time, only if you manually and dynamically load DLLs/shared libraries in your code you will have a real run-time error. The rule when developing code is: Prefer compile-time over link-time over load-time over run-time errors. The `=delete` allows a certain class of problems to be promoted from the lower classes to the "best" class (compiler-time error) with improved diagnostics. – Daniel Frey Sep 19 '13 at 06:36
  • Yes, I'm aware of this. I meant exactly manually loading shared libraries, with `dlopen` for example. – Kiril Kirov Sep 19 '13 at 06:47
12

The difference is that the purpose of the =delete code is explicit in it's purpose. Declaring functions as private / inaccessible was a trick. Although most people knew it, the error it generated was obscure (a linking/access level error instead of a semantical problem in the code - i.e. "you are using a deleted function").

utnapistim
  • 26,809
  • 3
  • 46
  • 82
3

One difference is that the old-fashioned form gives undefined behaviour if the class (or a friend) tries to destroy itself. Within class members and friends, the destructor is accessible, so there is no compile-time error if it's used. Instead, you get a violation of the One Definition Rule. In practice, this will cause a link error, but formally the behaviour is undefined.

Deleting the constructor (or other function) causes a compile error if the function is needed in any circumstances; and states the intent more explicitly, allowing the compiler to give better diagnostic messages. This is especially useful when functions are implicitly deleted due to something else being deleted.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

Another thing which hasn't been mentioned yet: when inheriting / overriding, you can't =delete a function which already has a body but you can change a public function into a private one, making it basically inaccessible from outside.

Miro Kropacek
  • 2,742
  • 4
  • 26
  • 41