一般导致程序崩溃的最重要原因之一就是试图解引用NULL指针。正如上几篇文章中所说的,智能指针RefCountPtr和ScopedPtr提供了运行时的诊断。但是,并不是所有的指针都是拥有某个对象所有的智能指针。因此为了对试图解引用一个不具有对象所有权的指针的行为进行诊断,引入一种并不删除它所指向的对象的“半智能”指针。例如,如下代码示例:
template <typename T> class Ptr { public: explicit Ptr(T* p = NULL) : ptr_(p) { } T* Get() const { return ptr_; } Ptr<T>& operator=(T* p) { ptr_ = p; return *this; } T* operator->() const { SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator -> on NULL pointer."); return ptr_; } T& operator*() const { SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator * on NULL pointer."); return *ptr_; } private: T* ptr_; };
尽管出现了操作符=,但它并不是告诉编译器当我们试图把一个Ptr<T>赋值给另一个Ptr<T>时该怎么做的赋值符。如果我们为这个类编写一个赋值操作符,它应该被声明为如下这种形式:
Ptr<T>& operator=(const Ptr<T>& that);
另外一种情况,如果建议我们用Ptr<T>代替T*,对于const T*指针该使用什么?答案为:Ptr<const T>。假设如下的这个类:
class MyClass { public: explicit MyClass(int id) : id_(id) { } int GetId() const { return id_; } void SetId(int id) { id_ = id; } private: int id_; };
scpp::Ptr<const MyClass> p(new MyClass(1)); cout<<"Id = "<<p->GetId()<<endl; //能够编译并运行 p->SetId(666); //无法通过编译
对于Ptr<T>模板指针具有以下特性:
(1)它并不拥有它所指向的对象的所有权,应该作为相同情况下原始指针的替代品;
(2)它默认被初始化为NULL;
(3)它提供了运行时诊断,当它本身为NULL时,如果对它进行调用,就可以对这种行为进行检测。
小结:
原文地址:http://blog.csdn.net/kerry0071/article/details/37923943