mozilla开源项目学习----智能指针(AutoPtr&AutoArrayPtr)
2015-11-26 11:16
507 查看
用过c++朋友一定都忘记释放过动态分配的内存。内存释放是一个很头痛的问题,一不小心就会造成内存泄漏。比如说,一个函数中分配了内存,但这个函数还有很多出口(return),我们不得不在每个出口去释放内存。这是一个很费时费力的的工作。但如果用了智能指针,在函数结束时,会智能的释放内存。这节省了程序员的工作,也减少程序员犯错。
在mozilla开源项目里用到了智能指针nsAutoPtr和nsAutoArrayPtr(两个c++模板类)。这两个类会在类生命周期结束时释放所管理的内存。在代码中使用这类时,就不必担心内存释放。
class Ptr
{
public:
Ptr(T* aPtr) : mPtr(aPtr)
{
}
operator T*() const
{
return mPtr;
}
private:
T* mPtr;
};
Ptr重载了隐式类转换,直接返回Ptr::mPtr成员值;
Ptr构造函数有一个参数,用于初始化Ptr::mPtr;
nsAutoPtr有三个构造函数。
nsAutoPtr的默认构造函数只将nsAutoPtr::mRawPtr初始化成0;
nsAutoPtr() : mRawPtr(0)
{
}
nsAutoPtr(Ptr aRawPtr) : mRawPtr(aRawPtr)
{
}
此构造函数使用Ptr类构造类初始化nsAutoPtr::mRawPtr指针。
nsAutoPtr(nsAutoPtr<T>& aSmartPtr)
: mRawPtr(a.SmartPtr.forget())
{
}
当使用智能指针A初始化另一个智能指针B时,被初始化的智能指针B将拥有智能指针B所管理的内存,而B将失败对内存管理。这个设计理由是,只有一个nsAutoPtr类管理这个内存。假设有两个nsAutoPtr A和b管理一个内存,当其中一个nsAutoPtr A生命周期结束,内存将被释放,那么B将指向一个非法内存地址。
nsAutoPtr<T>& operator=(T* rhs)
{
assign(rhs);
return *this;
}
此函数重载了右值为T* 的=运算符,nsAutoPtr首先释放原先管理内存,再管理rhs所指向内存。这避免泄漏原来管理的那内存。
nsAutoPtr<T>& operator=(nsAutoPtr& rhs)
{
assign(rhs.forget());
return *this;
}
此成员函数重载了右值为nsAutoPtr&的=运算符。 左值nsAutoPtr将释放管理的内存,再接管右值nsAutoPtr管理的内存。而右值nsAutoPtr将失去内存的管理权。这保证了这个内存只被一个nsAutoPtr管理。
operator T*() const
{
return get();
}
此函数重载了隐式类型转换。这主要是方便智能指针使用。例如 nsAutoPtr<int> a = new int; int * b = a;
b = a;这条语句不针产生编译错误,b 就是等于a的实例成员mRawPtr指向的内存。
T* operator->() const
{
NS_PRECONDITION(m_RawPtr != 0, “You can’t dereference a NULL nsAutoPtr with operator->(). ");
return get();
}
此成员函数重载->运算符。对nsAutoPtr<T> 类的操作转换成对T类型的操作。这也将方便nsAutoPtr的使用,就像是直接操作T类型的变量。
例如:
class A
{
public:
void FunctionA() {};
int nVa;
};
int main()
{
nsAutoPtr<A> a = new A;
a->FunctionA();
a->nVa;
return 0;
}
T& operator*() const
{
NS_PRECONDITION(mRawPtr != 0, “You can’t derefence a NULL nsAutoPtr width operator*().”);
return *get();
}
此函数重载了“*”运算。将对nsAutoPtr的运算转换成对nsAutoPtr<T>::mRawPtr的运算。
nsAutoPtr基本上对运算符都做了重载。将对自身的运算都转换到对成员T*的运算。这要在添加了nsAutoPtr的保护后,不会影响程序员的操作。而对nsAutoPtr<T>变量的操作,都写了另一些函数来实现, 这对nsAutoPtr<T>变量的操作是变麻烦了。但相对于带来的好处,这点麻烦还是承受的起的。
在mozilla开源项目里用到了智能指针nsAutoPtr和nsAutoArrayPtr(两个c++模板类)。这两个类会在类生命周期结束时释放所管理的内存。在代码中使用这类时,就不必担心内存释放。
AutoPtr:
Ptr是nsAutoPtr内部的类。注释说Ptr类阻止隐晦复制构造函数。class Ptr
{
public:
Ptr(T* aPtr) : mPtr(aPtr)
{
}
operator T*() const
{
return mPtr;
}
private:
T* mPtr;
};
Ptr重载了隐式类转换,直接返回Ptr::mPtr成员值;
Ptr构造函数有一个参数,用于初始化Ptr::mPtr;
nsAutoPtr有三个构造函数。
nsAutoPtr的默认构造函数只将nsAutoPtr::mRawPtr初始化成0;
nsAutoPtr() : mRawPtr(0)
{
}
nsAutoPtr(Ptr aRawPtr) : mRawPtr(aRawPtr)
{
}
此构造函数使用Ptr类构造类初始化nsAutoPtr::mRawPtr指针。
nsAutoPtr(nsAutoPtr<T>& aSmartPtr)
: mRawPtr(a.SmartPtr.forget())
{
}
当使用智能指针A初始化另一个智能指针B时,被初始化的智能指针B将拥有智能指针B所管理的内存,而B将失败对内存管理。这个设计理由是,只有一个nsAutoPtr类管理这个内存。假设有两个nsAutoPtr A和b管理一个内存,当其中一个nsAutoPtr A生命周期结束,内存将被释放,那么B将指向一个非法内存地址。
nsAutoPtr<T>& operator=(T* rhs)
{
assign(rhs);
return *this;
}
此函数重载了右值为T* 的=运算符,nsAutoPtr首先释放原先管理内存,再管理rhs所指向内存。这避免泄漏原来管理的那内存。
nsAutoPtr<T>& operator=(nsAutoPtr& rhs)
{
assign(rhs.forget());
return *this;
}
此成员函数重载了右值为nsAutoPtr&的=运算符。 左值nsAutoPtr将释放管理的内存,再接管右值nsAutoPtr管理的内存。而右值nsAutoPtr将失去内存的管理权。这保证了这个内存只被一个nsAutoPtr管理。
operator T*() const
{
return get();
}
此函数重载了隐式类型转换。这主要是方便智能指针使用。例如 nsAutoPtr<int> a = new int; int * b = a;
b = a;这条语句不针产生编译错误,b 就是等于a的实例成员mRawPtr指向的内存。
T* operator->() const
{
NS_PRECONDITION(m_RawPtr != 0, “You can’t dereference a NULL nsAutoPtr with operator->(). ");
return get();
}
此成员函数重载->运算符。对nsAutoPtr<T> 类的操作转换成对T类型的操作。这也将方便nsAutoPtr的使用,就像是直接操作T类型的变量。
例如:
class A
{
public:
void FunctionA() {};
int nVa;
};
int main()
{
nsAutoPtr<A> a = new A;
a->FunctionA();
a->nVa;
return 0;
}
T& operator*() const
{
NS_PRECONDITION(mRawPtr != 0, “You can’t derefence a NULL nsAutoPtr width operator*().”);
return *get();
}
此函数重载了“*”运算。将对nsAutoPtr的运算转换成对nsAutoPtr<T>::mRawPtr的运算。
nsAutoPtr基本上对运算符都做了重载。将对自身的运算都转换到对成员T*的运算。这要在添加了nsAutoPtr的保护后,不会影响程序员的操作。而对nsAutoPtr<T>变量的操作,都写了另一些函数来实现, 这对nsAutoPtr<T>变量的操作是变麻烦了。但相对于带来的好处,这点麻烦还是承受的起的。
相关文章推荐
- apache虚拟主机
- 如何规划构建一套大型的Citrix桌面虚拟化架构 - Part1
- jvmtop 监控
- IDEA 启动不 tomcat 单独能启 in directory apache-tomcat-7.0.52\bin"): CreateProcess error=2
- linux上创建PV/VG/LV
- tomcat启动出错
- 架构师:成为架构师可能会面临的问题
- linux命令行
- nginx初测
- codeforce #322C Developing Skills (优先队列)
- (转)hadoop基本操作命令
- OpenCV的随机数发生器
- ubuntu top命令学习日记
- linux上安装libpng库以及zlib库
- openssl windows 本地配置问题
- linux编程中的超时设置
- tomcat调优
- MySQL 高可用MMM
- Linux学习24_Linux安装系统时硬盘分区建议
- 图文讲解如何搭建Apache服务器