Auto ptr
在03版本中标准库第一次引入了智能指针std::auto_ptr,这也是当时唯一的智能指针类型。但是在11版本中,其被废弃。
定义大概如下:
template <typename _Tp>
class auto_ptr
{
private:
_Tp *_M_ptr;
public:
explicit auto_ptr(_Tp *__p = 0) throw();
auto_ptr(auto_ptr &__a) throw();
auto_ptr &operator=(auto_ptr &__a) throw();
~auto_ptr();
_Tp &operator*() const throw();
_Tp *operator->() const throw();
_Tp *get() const throw();
_Tp *release() throw();
void reset(_Tp *__p = 0) throw();
};
功能:
- 支持拷贝构造
- 支持拷贝赋值
- 支持operator -> 和 *解引用
- 支持指针变量reset
- 保证指针持有者唯一
有问题的使用场景
场景一:数组保存std::auto_ptr实例
std::vector<std::auto_ptr<People>> peoples;
// 这里实例化多个people并保存到数组中
...
std::auto_ptr<People> one = peoples[5];
...
std::cout << peoples[5]->get_name() << std::endl;
上面程序如果将std::auto_tr类型替换为原始指针,就不会有问题。但是这里却会导致程序报段错误崩溃!问题就出在:
std::auto_ptr<People> one = peoples[5];
这行代码会将peoples[5]中的指针所有权转移了!即该变量中的指针已经为null了。后续对解引用是不正确的。
原因在于std::auto_ptr支持operator=,为了确保指针所有者唯一,这里转移了所有权!
场景二:函数传参
void do_somthing(std::auto_ptr<People> people)
{
// 该函数内不对people变量执行各种隐式/显示的所有权转移和释放
...
}
std::auto_ptr<People> people(new People("jony"));
do_something(people);
...
std::cout << people->get_name() << std::endl;
这里对auto_ptr的使用与原始指针的使用完全相同。但是该代码还是会崩溃!问题就在于执行do_something()函数时,传递参数导致原变量的指针所有权转移了,即people变量实际已经变为null了!
原因在于std::auto_ptr支持拷贝构造,为了确保指针所有者唯一,这里转移了所有权!