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 copy-and-swap idiom.
So what exactly is the Rule of Four (and a half)? Which functions need to 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 to a default state.
//It need not be useful, but it should be swappable and deconstructable.
//In this case, the compiler provides an equivalent default.
//Foo() : resource(nullptr) {}
Foo() = default;
//Normal constructor, acquires resource
Foo(int value) : resource(new int(value)) {}
//Copy constructor
Foo(Foo const& other) {
resource = new int(*other.resource);
//Other resource copying happens here.
}
//Move constructor
//Delegates to default constructor to put us in safe state.
Foo(Foo&& other) : Foo() {
swap(other); //or std::swap(*this, other); if custom swap is omitted
}
//Assignment
Foo& operator=(Foo other) {
swap(other); //or std::swap(*this, other);
return *this;
}
//Destructor
~Foo() {
//The default constructor will initialize resource to nullptr.
if (resource != nullptr) delete resource;
//Other resource freeing happens here.
}
//Swap
void swap(Foo& other) {
using std::swap;
swap(resource, other.resource);
//Other resource swapping happens here.
}
//Swap for ADL
friend void swap(Foo& left, Foo& right) {
left.swap(right);
}
private:
int* resource;
};
Aucun commentaire:
Enregistrer un commentaire