五規則
Version >= C++ 11
C++ 11 引入了兩個新的特殊成員函式:移動建構函式和移動賦值運算子。由於你想要遵循 C++ 03 中的 Rule of Three 的所有相同的原因,你通常想要遵循 C++ 11 中的 Five of Rule:如果一個類需要五個特殊成員函式中的一個,並且如果移動語義如果需要,那麼它很可能需要五個。
但是,請注意,未遵循五法則通常不會被視為錯誤,而是錯過優化機會,只要仍然遵循三法則。如果編譯器通常不使用移動建構函式或移動賦值運算子,則它將在可能的情況下使用複製語義,從而導致由於不必要的複製操作而導致操作效率降低。如果類不需要移動語義,則不需要宣告移動建構函式或賦值運算子。
與三規則相同的例子:
class Person
{
char* name;
int age;
public:
// Destructor
~Person() { delete [] name; }
// Implement Copy Semantics
Person(Person const& other)
: name(new char[std::strlen(other.name) + 1])
, age(other.age)
{
std::strcpy(name, other.name);
}
Person &operator=(Person const& other)
{
// Use copy and swap idiom to implement assignment.
Person copy(other);
swap(*this, copy);
return *this;
}
// Implement Move Semantics
// Note: It is usually best to mark move operators as noexcept
// This allows certain optimizations in the standard library
// when the class is used in a container.
Person(Person&& that) noexcept
: name(nullptr) // Set the state so we know it is undefined
, age(0)
{
swap(*this, that);
}
Person& operator=(Person&& that) noexcept
{
swap(*this, that);
return *this;
}
friend void swap(Person& lhs, Person& rhs) noexcept
{
std::swap(lhs.name, rhs.name);
std::swap(lhs.age, rhs.age);
}
};
或者,複製和移動賦值運算子都可以用單個賦值運算子替換,它通過值而不是引用或右值引用來獲取例項,以便於使用複製和交換習慣用法。
Person& operator=(Person copy)
{
swap(*this, copy);
return *this;
}
從三規則延伸到五規則對於效能原因很重要,但在大多數情況下並非絕對必要。新增複製建構函式和賦值運算子可確保移動型別不會洩漏記憶體(在這種情況下,移動構造將簡單地回退到複製),但將執行呼叫者可能沒有預料到的副本。