template <typename T> classAuto_ptr1 { T* m_ptr {}; public: // Pass in a pointer to "own" via the constructor Auto_ptr1(T* ptr=nullptr) :m_ptr(ptr) { }
// The destructor will make sure it gets deallocated ~Auto_ptr1() { delete m_ptr; }
// Overload dereference and operator-> so we can use Auto_ptr1 like m_ptr. T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } };
// A sample class to prove the above works classResource { public: Resource() { std::cout << "Resource acquired\n"; } ~Resource() { std::cout << "Resource destroyed\n"; } };
intmain() { Auto_ptr1<Resource> res(new Resource()); // Note the allocation of memory here
// ... but no explicit delete needed
// Also note that we use <Resource>, not <Resource*> // This is because we've defined m_ptr to have type T* (not T)
return0; } // res goes out of scope here, and destroys the allocated Resource for us
将指针包含在类里,通过类的析构函数,可以做到自动释放内存。
但是这么做会有问题,例如两个Auto_ptr1可能管理同一个指针:
1 2 3 4 5 6 7
intmain() { Auto_ptr1<Resource> res1(new Resource()); Auto_ptr1<Resource> res2(res1); // Alternatively, don't initialize res2 and then assign res2 = res1;
// A copy constructor that implements move semantics Auto_ptr2(Auto_ptr2& a) // note: not const { // We don't need to delete m_ptr here. This constructor is only called when we're creating a new object, and m_ptr can't be set prior to this. m_ptr = a.m_ptr; // transfer our dumb pointer from the source to our local object a.m_ptr = nullptr; // make sure the source no longer owns the pointer }
// An assignment operator that implements move semantics Auto_ptr2& operator=(Auto_ptr2& a) // note: not const { if (&a == this) return *this;
delete m_ptr; // make sure we deallocate any pointer the destination is already holding first m_ptr = a.m_ptr; // then transfer our dumb pointer from the source to the local object a.m_ptr = nullptr; // make sure the source no longer owns the pointer return *this; }
// Copy constructor // Do deep copy of a.m_ptr to m_ptr Auto_ptr3(const Auto_ptr3& a) { m_ptr = new T; *m_ptr = *a.m_ptr; }
// Copy assignment // Do deep copy of a.m_ptr to m_ptr Auto_ptr3& operator=(const Auto_ptr3& a) { // Self-assignment detection if (&a == this) return *this;
// Release any resource we're holding delete m_ptr;
// Copy the resource m_ptr = new T; *m_ptr = *a.m_ptr;
// Copy constructor // Do deep copy of a.m_ptr to m_ptr Auto_ptr4(const Auto_ptr4& a) { m_ptr = new T; *m_ptr = *a.m_ptr; }
// Move constructor // Transfer ownership of a.m_ptr to m_ptr Auto_ptr4(Auto_ptr4&& a) noexcept : m_ptr(a.m_ptr) { a.m_ptr = nullptr; // we'll talk more about this line below }
// Copy assignment // Do deep copy of a.m_ptr to m_ptr Auto_ptr4& operator=(const Auto_ptr4& a) { // Self-assignment detection if (&a == this) return *this;
// Release any resource we're holding delete m_ptr;
// Copy the resource m_ptr = new T; *m_ptr = *a.m_ptr;
return *this; }
// Move assignment // Transfer ownership of a.m_ptr to m_ptr Auto_ptr4& operator=(Auto_ptr4&& a) noexcept { // Self-assignment detection if (&a == this) return *this;
// Release any resource we're holding delete m_ptr;
// Transfer ownership of a.m_ptr to m_ptr m_ptr = a.m_ptr; a.m_ptr = nullptr; // we'll talk more about this line below
// Copy constructor -- no copying allowed! Auto_ptr5(const Auto_ptr5& a) = delete;
// Move constructor // Transfer ownership of a.m_ptr to m_ptr Auto_ptr5(Auto_ptr5&& a) noexcept : m_ptr(a.m_ptr) { a.m_ptr = nullptr; }
// Copy assignment -- no copying allowed! Auto_ptr5& operator=(const Auto_ptr5& a) = delete;
// Move assignment // Transfer ownership of a.m_ptr to m_ptr Auto_ptr5& operator=(Auto_ptr5&& a) noexcept { // Self-assignment detection if (&a == this) return *this;
// Release any resource we're holding delete m_ptr;
// Transfer ownership of a.m_ptr to m_ptr m_ptr = a.m_ptr; a.m_ptr = nullptr;