For properly handling object copying, the rule of thumb is the Rule of Three. With C++11, move semantics are a thing, so instead it's the Rule of Five. However, in discussions around here and on the internet, I've also seen references to the Rule of Four (and a half), which is a combination of the Rule of Five and the copy-and-swap idiom.
So what exactly is the Rule of Four (and a half)? Which functions need to be implemented, and what should each function's body look like? Which function is the half? Are there any disadvantages or warnings for this approach, compared to the Rule of Five?
Here's a reference implementation that resembles my current code. If this is incorrect, what would a correct implementation look like?
//I understand that in this example, I could just use `std::unique_ptr`.
//Just assume it's a more complex resource.
#include <utility>
class Foo {
public:
//We must have a default constructor so we can swap during copy construction.
//It need not be useful, but it should be swappable and deconstructable.
//It can be private, if it's not truly a valid state for the object.
Foo() : resource(nullptr) {}
//Normal constructor, acquire resource
Foo(int value) : resource(new int(value)) {}
//Copy constructor
Foo(Foo const& other) {
//Copy the resource here.
resource = new int(*other.resource);
}
//Move constructor
//Delegates to default constructor to put us in safe state.
Foo(Foo&& other) : Foo() {
swap(other);
}
//Assignment
Foo& operator=(Foo other) {
swap(other);
return *this;
}
//Destructor
~Foo() {
//Free the resource here.
//We must handle the default state that can appear from the copy ctor.
//(The if is not technically needed here. `delete nullptr` is safe.)
if (resource != nullptr) delete resource;
}
//Swap
void swap(Foo& other) {
using std::swap;
//Swap the resource between instances here.
swap(resource, other.resource);
}
//Swap for ADL
friend void swap(Foo& left, Foo& right) {
left.swap(right);
}
private:
int* resource;
};
The rule of three and rule of five are rules of thumb in C++ for the building of exception-safe code and for formalizing rules on resource management. The rules prescribe how the default members of a class should be used to achieve these goals systematically.
Constructor in C++ is a special method that is invoked automatically at the time of object creation. It is used to initialize the data members of new objects generally. The constructor in C++ has the same name as the class or structure. Constructor is invoked at the time of object creation.
In C++ we often associate three language features with copy control: destructors, copy constructors, and assignment operators. We will call these the Big 3 because often times when you need to write any one of them, you most likely will need to write the other two.
Which of the followings is/are automatically added to every class, if we do not write our own. Explanation: In C++, if we do not write our own, then compiler automatically creates a default constructor, a copy constructor and a assignment operator for every class.
So what exactly is the Rule of Four (and a half)?
“The Rule of The Big Four (and a half)" states that if you implement one of
then you must have a policy about the others.
Which functions need to implemented, and what should each function's body look like?
move constructor (using default constructor and swap) :
S(S&& s) : S{} { swap(*this, s); }
assignment operator (using constructor and swap)
S& operator=(S s) { swap(*this, s); }
destructor (deep copy of your resource)
std::swap
uses move (or copy) constructor, which would lead to infinite recursion.Which function is the half?
From previous article:
"To implement the Copy-Swap idiom your resource management class must also implement a swap() function to perform a member-by-member swap (there’s your “…(and a half)”)"
so the swap
method.
Are there any disadvantages or warnings for this approach, compared to the Rule of Five?
The warning I already wrote is about to write the correct swap to avoid the infinite recursion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With