15

I was just musing about the number of questions here that either are about the "big three" (copy constructor, assignment operator and destructor) or about problems caused by them not being implemented correctly, when it occurred to me that I could not remember the last time I had implemented them myself. A swift grep on my two most active projects indicate that I implement all three in only one class out of about 150.

That's not to say I don't implement/declare one or more of them - obviously base classes need a virtual destructor, and a large number of my classes forbid copying using the private copy ctor & assignment op idiom. But fully implemented, there is this single lonely class, which does some reference counting.

So I was wondering am I unusual in this? How often do you implement all three of these functions? Is there any pattern to the classes where you do implement them?

  • 2
    Reading this question makes me so happy that I don't have to write C++! (Of course, this probably explains why I have difficulty modifying other people's C++.) – Norman Ramsey May 01 '10 at 14:49
  • 6
    -1 @Norman No need to go against C++. If you don't have to write C++ code go to other question. I have never understood the people that because they don't use something, they want than nobody use it, and vice versa. – Vicente Botet Escriba May 01 '10 at 15:06
  • 4
    @Norman I would have thought it (and the answers) is encouraging - you very rarely need to do a complex task. –  May 01 '10 at 15:10
  • @Neil Oh the answers are definitely encouraging. It's like the question about break statements a while back---I was astonished at how seldom I use them. I even upvoted the question :-) It's just that I like a language like Icon or CLU where pointers/objects have reference semantics and assignment always means the same thing. – Norman Ramsey May 01 '10 at 18:52
  • 4
    @Norman Some people can program fluently in several different programming languages, using several different paradigms, as the need occurs. If you can't, there is no value in bad-mouthing the language(s) that you are uncomfortable with. –  May 01 '10 at 19:03
  • 1
    @Neil I program fluently in several different programming languages, using several different paradigms, as the need occurs. I have written tens of thousands of lines of code in statically typed hybrid object-oriented languages, which is the proper classification for C++. I badmouth C++ not because I am uncomfortable but because it's a pathetic excuse for a design. It is important to badmouth bad design so people can learn that bad design is not all there is. Criticizing C++ is like shooting fish in a barrel, but Bjarne is more heavyweight than I am and he can take it. Besides, he won :-) – Norman Ramsey May 01 '10 at 21:04
  • 2
    @Norman So you are basically wasting your time, and to a lesser extent ours? –  May 01 '10 at 21:10
  • 1
    @Neil if one person sees this exchange of comments and starts to wonder why the Big Three exist anyway and what the world would be like in a language in which the Big Three were unnecessary, I will consider the time well spent. (Also, I'm having trouble seeing my comments as more time-wasting than your telling a clueless person to get out of programming.) But it's your post, so I'll stop here and encourage you to have the last word. – Norman Ramsey May 01 '10 at 21:16
  • 3
    @Norman OK I will. C++ is the kind of language that allows the kind of language you prefer to come into existence. –  May 01 '10 at 21:24
  • @Vicente: I have students who try to use C++, cut themselves, and then I have to mop up the blood. – Norman Ramsey Jun 04 '10 at 15:01

6 Answers6

2

I think that it's rare that you need all three. Most classes that require an explicit destructor aren't really suitable for copying.

It's just better design to use self-destructing members (which normally don't require things like copy-construction) than a big explicit destructor.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • The pImpl idiom is a commonly-used counterexample. – Marcelo Cantos May 01 '10 at 13:38
  • 1
    Even if you decided that you didn't want the behaviour of std::auto_ptr, you would just write yourself a pimpl_ptr class, and use that behaviour, in all your PIMPL classes. Now you have X classes that use PIMPL that don't require this, and 1 class that deals with the behaviour of your personal pimpl_ptr that does, resulting in the majority of your classes not needing it. – Puppy May 02 '10 at 12:31
1

Like you, almost never.

But I'm not tied to the STL approach of programming where you copy everything in and around in containers - usually if it's not a primitive, I'll use a pointer, smart or otherwise.

I mainly use RAII patterns, thus avoid writing destructors. Although, I do put empty bodies in my .cc file to help keep code bloat down.

And, like you, I'll declare them private and unimplemented to prevent any accidental invoking.

Stephen
  • 47,994
  • 7
  • 61
  • 70
  • 4
    Huh? Destructors are the cornerstone of RAII. Or did you mean you exclusively use RAII classes written by others? – Ben Voigt May 01 '10 at 14:56
  • Empty function bodies cause less code bloat if they are in the header file so they can be inlined. But I can't imagine why to define an empty destructor. – Potatoswatter May 01 '10 at 18:06
  • @Ben Voigt, obviously yes, destructors are fundamental to raii... but I usually don't need to write my own RAII classes, and when I use Ravi members, I don't need to clean them up in destructors. – Stephen May 01 '10 at 19:31
  • @potatoswatter: empty constructors may have lots of compiler generated code, construction of member variables and initialization of base classes. That isn't always a good candidate for inlining. Same goes for destructors. If you put them in header files, that code will be generated in all files that include it. – Stephen May 01 '10 at 19:34
  • What's the relevance of your last, italicised sentence? Or is it some kind of sig? –  May 01 '10 at 20:10
  • @Neil Butterworth, your question referred to the amount of questions for "the Big 3". I was responding to that. Not too relevant, removed. – Stephen May 01 '10 at 22:38
1

I rarely implement them, but often declare them private (copy constructors and assignemt operators, that is).

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
0

Most of the time, hardly ever. This is because the members that are used (reference based smart ptr, etc) already implement the proper semantics, or the object is non-copyable.

A few patterns come up when I find myself implementing these:

  1. destructive copy , i.e. move pattern like auto_ptr or lock
  2. dispose pattern which hardly every comes up in C++, but I've used it about three times in my career (and just a week ago in fact)
  3. pimpl pattern, where the pimpl is fwd declared in the header, and managed by a smart ptr. Then the empty dtor goes in the .cc file but still classifies as "not complier generated"

And one other trivial one that prints "I was destroyed" when I think I might have a circular reference somewhere and just want to make sure.

Lance Diduck
  • 1,513
  • 9
  • 11
0

It really depends on what type of problems you are working on. I have been working on a new project for the past few months and I think every class inherits from boost::noncopyable. Nine months ago I worked on a different project that used PODs quite a bit and I leveraged automatic copy ctor and assignment operator. If you are using boost::shared_ptr (and you should be), it should be rare to write your own copy ctor or assignment operator nowadays.

Chris Hafey
  • 601
  • 3
  • 5
0

Any class that owns some pointers members need to define this three operations to implement deep copy (See here for a deep description).

Vicente Botet Escriba
  • 4,305
  • 1
  • 25
  • 39
  • It's not a question of owning the pointers, but of owning what they point to. A class can contain pointer without ownership, and in that case probably does not need the big three. And I'm very anti- the term "deep copy" - there is only one kind of copy operation - the correct one. –  May 01 '10 at 15:13
  • @Neil Butterworth: You've previously commented on an answer from me that the term "deep copy" isn't of much use. (See here: http://stackoverflow.com/questions/2657810/2657824#2657824) In that other thread you didn't explicitly say that "there's only one kind of copy operation - the correct one". I'm curious: Which would would that be? The correct one in a particular case, or one general solution? – stakx - no longer contributing May 01 '10 at 15:38
  • @stakx The correct one for the particular class, which might be deep, shallow or more likely somewhere in between. –  May 01 '10 at 15:39
  • @Neil: I'd fully agree on that. Thanks for answering. – stakx - no longer contributing May 01 '10 at 15:41
  • 2
    @Neil: in theory if you had a class with a `shared_ptr` to something mutable, then "deep copy" and "shallow copy" are different operations which might each be desirable for different users. Only one of them can be the copy ctor. Probably the shallow copy, with a deep copy and deep-assign available as member functions, but I don't think it's a matter of "correct" if they're both needed by different users. Of course I agree that the language might still be inadequate if there's a question of *how* deep (i.e. if that mutable thing itself has pointers of some kind). – Steve Jessop May 01 '10 at 16:52
  • 1
    @Neil I think that your playing with the words. When I say owns a pointer, I hope you will be able to understand me. I hope also that you agree with me that when a class has ownership with other classes these three operations must be defined. That was exactly the question. – Vicente Botet Escriba May 01 '10 at 17:23
  • @Vicente Just trying to be accurate. Some people make dogmatic statements like "if a class contains pointers, it must implement the big three", which isn't true. I was not clear what you meant by "owning pointers" (still am not, actually). –  May 01 '10 at 17:33
  • 1
    @Neil You can be anti whatever you want. The term "deep copy" exists and has a clear meaning. – Vicente Botet Escriba May 01 '10 at 17:34
  • @Vicente Lots of terms exist. Whether they can usefully be applied to C++ is another matter. And I would strongly dispute the "clear meaning". –  May 01 '10 at 17:39