Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
186 views
in Technique[技术] by (71.8m points)

c++ - What is the Rule of Four (and a half)?

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;
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

  • The copy constructor
  • The assignment operator
  • The move constructor
  • The destructor
  • The swap function

then you must have a policy about the others.

Which functions need to implemented, and what should each function's body look like?

  • default constructor (which could be private)
  • copy constructor (Here you have real code to handle your resource)
  • 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)

  • friend swap (doesn't have default implementation :/ you should probably want to swap each member). This one is important contrary to the swap member method: 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...