I'm familiar with the notion in c++ of the rule of 3, however since the release of C++11 I've seen some sources suggesting it should be extended to a "rule of 5", I.e. the move constructor and move assignment operator should also be implemented whenever the others are. What is the rationale behind such a rule? My understanding is that in most cases implementation of move semantics is only necessary as an optimization - am I wrong about this, or is the so-called rule of five about optimizing my code (and, therefore, substantially less important than the rule of 3, which is about avoiding pitfalls that can lead to unexpected behaviors)?
-
2possible duplicate of [The rule of 5 - to use it or not?](http://programmers.stackexchange.com/questions/144092/the-rule-of-5-to-use-it-or-not) – Robert Harvey Dec 25 '14 at 21:04
-
2Despite the title, that question does not address the same subject as mine; I.did read it prior to posting this, but it does not really cover this ground. – Jules Dec 25 '14 at 21:08
-
http://meta.stackexchange.com/questions/194476/someone-flagged-my-question-as-already-answered-but-its-not – gnat Dec 25 '14 at 21:12
-
1Related: http://stackoverflow.com/q/4782757 – Robert Harvey Dec 26 '14 at 06:09
-
1What can we tell you here that the [Wikipedia article on Rule of 3 and Rule of 5](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)) doesn't already explain? – Robert Harvey Dec 26 '14 at 06:15
-
I tried to include more from the question body into the title to make more clear it is not a duplicate, and Wikipedia does not answer it. – Doc Brown Dec 26 '14 at 06:58
-
1@RobertHarvey: please don't tell me that wikipedia article explains it well... – Karoly Horvath Dec 26 '14 at 08:58
-
1In the future, when someone asks you why some other resource doesn't answer your question, *please tell us why*. Don't merely dismiss our question with the tautology that it doesn't. – Robert Harvey Dec 26 '14 at 16:43
2 Answers
Move semantics were added to C++11 in such a way that the "rule of 3" is still valid and sufficient to avoid the pitfalls that it is meant to avoid (althogh there are better ways in most situations by applying the "rule of 0").
There are also no additional pitfalls added to the language that the "rule of 5" would help you avoid. In that sense, the rule of 5 is more about optimization than about avoiding pitfalls.
On the other hand, treating the "rule of 5" as an extension to the "rule of 3" does help you to remember that in C++11 there are two additional special member functions that you need to think about when your class does something special that needs a destructor or copy-constructor.
And although move semantics are an optimization, providing a move-constructor and/or move-assignment operator doesn't mean you are prematurely optimising, just like selecting the right algorithm isn't a premature optimization.
Adding support for move semantics to your class, when it makes sense, usually takes little effort and doesn't detract from the readability/maintainability of the code.

- 71,712
- 20
- 110
- 179
-
I downvoted you principally because your advice would entail implementing three to five redundant operations per class. – DeadMG Dec 26 '14 at 13:52
-
1@DeadMG: That only shows you don't understand the "rule of three". In what way am I recommending to implement redundant operations? – Bart van Ingen Schenau Dec 26 '14 at 15:15
-
The three, or five. Both of those rules are made obsolete by unique_ptr (five didn't even live long enough to become a real rule) and involve implementing copy and move operations for absolutely no benefit at all that just make the code less reliable and maintainable. I understand the rule of three just fine- it just only applies to C++03 and not C++11. – DeadMG Dec 26 '14 at 16:42
-
@DeadMG: I agree that `std::unique_ptr` reduces the number of times that you need a custom copy/move-constructor, but I don't agree that it reduces the need to 0. As long as that need is non-zero, there is a use for the rule of three/five. – Bart van Ingen Schenau Dec 26 '14 at 17:33
-
That's not true. Those rules are centered around bad destructions, and unique_ptr guarantees safety. If you don't implement an operation, you just won't have it, it won't be broken. Also, even if you still need them in a few special cases, in the general case, they are obsolete. You should not be giving out advice that only applies to a tiny minority of niche cases without giant warning labels on it stating that it's terrible and unreliable in virtually every case that every reader will ever encounter. Especially when the questioner gives no indication that any such special case applies. – DeadMG Dec 26 '14 at 18:36
-
1@DeadMG: Even in C++03/C++98 the "rule of three" is only applicable to a minority of all classes that one would write. As the question was about the difference between the rule of three and the rule of five, I didn't see the need for warnings that apply equally to both and have applied since C++98. `std::uniqu_ptr` didn't change anything there. – Bart van Ingen Schenau Dec 26 '14 at 20:25
The Rule of Five is ex-idiomatic. It was only idiomatic for a very brief period before the Rule of Zero.
The principle of the Rule of 3 became obsolete when writing your own resource-handling classes became obsolete, which is when your compiler supports rvalue references. If you implement in terms of unique_ptr, which you can for virtually every resource because the deleter is so customizable, you only need a custom copy assignment and copy constructor- so two. If you need to support copying. There's no reason to implement your own destructor, move assignment operator, or move constructor in the vast majority of cases.
Rule of Three code isn't broken but it's much harder to maintain than Rule of Zero code and not as efficient either. Move operations offer correctness in many cases like unique_ptr
so you should strive to support them wherever possible.
It's copy operations that are now largely redundant in the face of moves, not the other way around.
In other words, unique_ptr is so flexible, and defaulted operations so useful, that there's hardly ever any reason to implement your own special members anymore. In fact, there's hardly any reason to implement your own resource handling classes. And since those classes virtually never exist, there's no reason to to have an idiom to construct them.

- 36,794
- 8
- 70
- 139
-
This is an interesting response, and I can certainly see the attraction of the rule of zero, but I do a lot of interacting with os resources in my code and prefer to encapsulate them in a class with a destructor rather than relying on client code to configure an appropriate delete operation. – Jules Dec 26 '14 at 16:02
-
@Jules: Except the Standard already provides one class that can handle every OS resource in that exact fashion- `std::unique_ptr`. Even if you wrap it in your own class, you can still just default the members instead of needing to implement them yourself. – DeadMG Dec 26 '14 at 16:40