c++ template学习记录
使用模板将实际类型的指针进行封装
当变量退出作用域 自动delete
// 1111.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" template <typename T> class Holder { private: T* ptr; // refers to the object it holds (if any) public: // default constructor: let the holder refer to nothing Holder() : ptr(0) { } // constructor for a pointer: let the holder refer to where the pointer refers explicit Holder(T* p) : ptr(p) { } // destructor: releases the object to which it refers (if any) ~Holder() { delete ptr; } // assignment of new pointer Holder<T>& operator= (T* p) { delete ptr; ptr = p; return *this; } // pointer operators T& operator* () const { return *ptr; } T* operator-> () const { return ptr; } // get referenced object (if any) T* get() const { return ptr; } // release ownership of referenced object void release() { ptr = 0; } // exchange ownership with other holder void exchange_with(Holder<T>& h) { std::swap(ptr, h.ptr); } // exchange ownership with other pointer void exchange_with(T*& p) { std::swap(ptr, p); } private: // no copying and copy assignment allowed Holder(Holder<T> const&); Holder<T>& operator= (Holder<T> const&); }; class Something { public: void perform() const { } }; void do_two_things() { Holder<Something> first(new Something); first->perform(); Holder<Something> second(new Something); second->perform(); } int main() { do_two_things(); }
// 1111111.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stddef.h> #include <iostream> #include <vector> using namespace std; size_t* alloc_counter() { return ::new size_t; } void dealloc_counter(size_t* ptr) { ::delete ptr; } class SimpleReferenceCount { private: size_t* counter; // the allocated counter public: SimpleReferenceCount() { counter = NULL; } // default copy constructor and copy-assignment operator // are fine in that they just copy the shared counter public: // allocate the counter and initialize its value to one: template<typename T> void init(T*) { counter = alloc_counter(); *counter = 1; } // dispose of the counter: template<typename T> void dispose(T*) { dealloc_counter(counter); } // increment by one: template<typename T> void increment(T*) { ++*counter; } // decrement by one: template<typename T> void decrement(T*) { --*counter; } // test for zero: template<typename T> bool is_zero(T*) { return *counter == 0; } }; class StandardArrayPolicy { public: template<typename T> void dispose(T* array) { delete[] array; } }; class StandardObjectPolicy { public: template<typename T> void dispose(T* object) { delete object; } }; template<typename T, typename CounterPolicy = SimpleReferenceCount, typename ObjectPolicy = StandardObjectPolicy> class CountingPtr : private CounterPolicy, private ObjectPolicy { private: // shortcuts: typedef CounterPolicy CP; typedef ObjectPolicy OP; T* object_pointed_to; // the object referred to (or NULL if none) public: // default constructor (no explicit initialization): CountingPtr() { this->object_pointed_to = NULL; } // a converting constructor (from a built-in pointer): explicit CountingPtr(T* p) { this->init(p); // init with ordinary pointer } // copy constructor: CountingPtr(CountingPtr<T, CP, OP> const& cp) : CP((CP const&)cp), // copy policies OP((OP const&)cp) { this->attach(cp); // copy pointer and increment counter } // destructor: ~CountingPtr() { this->detach(); // decrement counter // (and dispose counter if last owner) } // assignment of a built-in pointer CountingPtr<T, CP, OP>& operator= (T* p) { // no counting pointer should point to *p yet: assert(p != this->object_pointed_to); this->detach(); // decrement counter // (and dispose counter if last owner) this->init(p); // init with ordinary pointer return *this; } // copy assignment (beware of self-assignment): CountingPtr<T, CP, OP>& operator= (CountingPtr<T, CP, OP> const& cp) { if (this->object_pointed_to != cp.object_pointed_to) { this->detach(); // decrement counter // (and dispose counter if last owner) CP::operator=((CP const&)cp); // assign policies OP::operator=((OP const&)cp); this->attach(cp); // copy pointer and increment counter } return *this; } // the operators that make this a smart pointer: T* operator-> () const { return this->object_pointed_to; } T& operator* () const { return *this->object_pointed_to; } // additional interfaces will be added later //... private: // helpers: // - init with ordinary pointer (if any) void init(T* p) { if (p != NULL) { CounterPolicy::init(p); } this->object_pointed_to = p; } // - copy pointer and increment counter (if any) void attach(CountingPtr<T, CP, OP> const& cp) { this->object_pointed_to = cp.object_pointed_to; if (cp.object_pointed_to != NULL) { CounterPolicy::increment(cp.object_pointed_to); } } // - decrement counter (and dispose counter if last owner) void detach() { if (this->object_pointed_to != NULL) { CounterPolicy::decrement(this->object_pointed_to); if (CounterPolicy::is_zero(this->object_pointed_to)) { // dispose counter, if necessary: CounterPolicy::dispose(this->object_pointed_to); // use object policy to dispose the object pointed to: ObjectPolicy::dispose(this->object_pointed_to); } } } }; void test1() { std::cout << "\ntest1():\n"; CountingPtr<int> p0; { CountingPtr<int> p1(new int(42)); std::cout << "*p1: " << *p1 << std::endl; *p1 = 17; std::cout << "*p1: " << *p1 << std::endl; CountingPtr<int> p2 = p1; std::cout << "*p2: " << *p2 << std::endl; *p1 = 33; std::cout << "*p2: " << *p2 << std::endl; p0 = p2; std::cout << "*p0: " << *p0 << std::endl; ++*p0; ++*p1; ++*p2; std::cout << "*p0: " << *p0 << std::endl; std::cout << "*p1: " << *p1 << std::endl; std::cout << "*p2: " << *p2 << std::endl; } std::cout << "after block: *p0: " << *p0 << std::endl; } void test2() { std::cout << "\ntest2():\n"; { CountingPtr<int> p0(new int(42)); CountingPtr<int> p2 = p0; } CountingPtr<int> p1(new int(42)); std::cout << "qqq" << std::endl; std::vector<CountingPtr<int> > coll; std::cout << "qqq" << std::endl; coll.push_back(p1); std::cout << "qqq" << std::endl; coll.push_back(p1); std::cout << "qqq" << std::endl; std::cout << "qqq" << std::endl; ++*p1; ++*coll[0]; std::cout << *coll[1] << std::endl; } int main() { test1(); test2(); }