C++智能指针的理念是用对象将内置的指针包裹起来。这些智能指针要么指向某个对象,要么等于NULL,也就是说,他们总能得到初始化,而且绝对不会指向已经释放的内存。
- 智能指针如果不是NULL,那么必须指向有效的内存。
- 智能指针要带有引用计数,而且要将其所指的内存合理地释放掉(这意味着,它能够安全地应对异常,同时又不会发生内存泄漏)。
- 智能指针用起来应该与内置地指针差不多
由于智能指针用起来与内置指针差不多,因此,必须以非侵入式的方式来实现。假如用侵入式的办法去做,那就需要设计公共基类。所有想要用该指针来指代的类,都必须继承那个基类,因为只有继承了那个基类,这些类的对象才能够获得引用计数的能力,从而被那个智能指针引用。用这种方法来实现智能指针,其适用范围仅局限与用户自定义的类型,而无法涵盖int和float这样的内置类型。反之,非入侵的方式可以同时涵盖这两个方面,因为无论使用内置类型还是用户自定义的类型,智能指针都会自己想办法来记录引用计数,而不需要我们对类型做修改。
有了智能指针,我们就不用担心内存管理问题。由于这些指针能够安全地复制、运行在多线程环境中并且能够安全应对异常状态,因此绝对不会指向已经释放地内存。
C++标准库提供了一种名为auto_ptr的智能指针。这种指针称为自动指针,它拥有其所指向的那个对象。这意味着指针在析构的时候,会将该对象所占据的内存一起释放掉。这种指针本身并不负责分配内存,也不会统计与其对象所占据的那块内存有关的引用计数。
auto_ptr类重载了*与->运算符,使得用户可以向普通指针一样去访问动态对象。如果想获取与它所封装的那个原始指针,可以调用get方法。如
std::auto_ptr<int> ptr1(new int(5));
*ptr1 = 4;
std::cout<<*ptr1<<std::endl;
int* ptr2 = ptr1.get();
*ptr2 = 3;
std::cout<<*ptr1<<","<<*ptr2<<std::endl;
智能指针还提供release方法,用来与它所管理的内存对象脱离关系,并将原始的指针返回给调用者。现在假设编写一个这样的函数:该函数动态分配某个对象,并且把指向该对象的普通指针返回给调用方。此外,函数还要为对象做很多初始化工作,如果这些工作任务在执行的时候出错,那么函数就会从不同的地方退出。这样的函数用自动指针就会比用内置指针更加简洁。
foo *get_new_foo(void)
{
std::auto_ptr<foo> obj(new foo);
//下面的操作会抛出异常,得益于智能指针,我们可以不用管他
obj->do_something();
obj->do_something_else();
return obj.release();
}
自动指针是不可以被复制的。如果被复制,会导致原有的指针失效,使用会出现问题。