类和五个特殊的函数紧密联系在一起,它们分别是析构函数destructor,拷贝构造函数(copy construct,移动构造函数(move constructor),拷贝赋值函数(copy assignment operator)和移动赋值函数(copy assignment operator)。当类中含有指针作为数据成员时,默认的拷贝以及析构函数会出现问题,必须自己定义。释放自己定义的动态内存,并且在拷贝时实施深拷贝。
#include<iostream> using namespace std; class IntCell { public: explicit IntCell(int initialValue = 0) { storedValue = new int{ initialValue }; } ~IntCell() { delete storedValue; } IntCell(const IntCell& rhs) { storedValue = new int{ *rhs.storedValue }; } IntCell(IntCell&& rhs) :storedValue{ rhs.storedValue } { rhs.storedValue = nullptr; } IntCell& operator=(const IntCell& rhs) { IntCell copy = rhs; swap(*this, copy); return *this; } IntCell& operator=(IntCell&& rhs) { swap(storedValue, rhs.storedValue); return *this; } private: int *storedValue; }; int main() { IntCell a{ 2 }; IntCell b = a; IntCell c; b = move(c); return 0; }
注意:
swap是通过三次移动实现的
template<class _Ty, class> inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty> && is_nothrow_move_assignable_v<_Ty>) { // exchange values stored at _Left and _Right _Ty _Tmp = _STD move(_Left); _Left = _STD move(_Right); _Right = _STD move(_Tmp); }因此移动赋值中交换的是成员,若改为对象则会出现无休止递归的情况,因为在swap中右出现了移动赋值。拷贝构造函数传递的是常量引用,若不是引用也会出现无休止递归的情形。