オブジェクトのコピーを適切に処理するための経験則は、Rule of Threeです。C++11 では、ムーブ セマンティクスが問題になるため、代わりにRule of Five を使用します。ただし、ここやインターネットでの議論では、Rule of Five と copy-and-swap のイディオムを組み合わせたRule of Four (and a half)への言及も見ました。
では、4 (半) のルールとは正確には何ですか? どの関数を実装する必要があり、各関数の本体はどのように見えるべきですか? 半分はどの機能ですか?ルール・オブ・ファイブと比較して、このアプローチの欠点や警告はありますか?
これは、私の現在のコードに似た参照実装です。これが正しくない場合、正しい実装はどのようになりますか?
//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;
};