1.普通指针的用法:
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;
class Monster
{
public:
Monster(){
cout << "Monster construct\n";
};
~Monster(){
cout << "Monster destruct\n";
};
void doSomething(){
cout << "Monster doSomething\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Monster* pMonster = new Monster();// new一块内存
pMonster->doSomething();
delete pMonster;// 释放 一块内存,调用monster的析构函数
pMonster = nullptr;
return 0;;
}
运算结果:
Monster construct
Monster doSomething
Monster destruct
请按任意键继续. . .
2.std::auto_ptr的用法
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;
class Monster
{
public:
Monster(){
cout << "Monster construct\n";
};
~Monster(){
cout << "Monster destruct\n";
};
void doSomething(){
cout << "Monster doSomething\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<Monster> monster(new Monster);// 使用智能指针,auto_ptr的对象monster在出了作用域之后就会释放,monster在析构时同时会delete成员指针
monster->doSomething();
return 0;;
}
运行结果:
Monster construct
Monster doSomething
Monster destruct
请按任意键继续. . .
auto_ptr的缺点:
复制auto_ptr对象时,把指针指传给复制出来的对象,原有对象的指针成员随后重置为nullptr。
这说明auto_ptr是独占性的,不允许多个auto_ptr指向同一个资源。
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;
class Monster
{
public:
Monster(){
cout << "Monster construct\n";
};
~Monster(){
cout << "Monster destruct\n";
};
void doSomething(){
cout << "Monster doSomething\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<Monster> monster(new Monster);// 使用智能指针,auto_ptr的对象monster在出了作用域之后就会释放,monster在析构时同时会delete成员指针
monster->doSomething();// 怪物做某事
std::auto_ptr<Monster> monster2 = monster;// 转移指针,此时原指针monster变为空
monster2->doSomething();// 怪物做某事
monster->doSomething();// 此时报错,指针已经转移,monster为野指针
return 0;;
}
运行结果指针赋值后,原来的指针变为nullptr。
这说明auto_ptr是独占性的,不允许多个auto_ptr指向同一个资源。
注意:
虽然本文简单介绍了auto_ptr。
但是不要用auto_ptr! 不要用auto_ptr!
虽然它是c++11以前的最原始的智能指针,但是在c++11中已经被弃用(使用的话会被警告)了。
它的替代品,也就是c++11新智能指针unique_ptr,shared_ptr,weak_ptr将在下文出现
3.auto_ptr的实现写法:
3.1 需求分析
- 这个类首先是一个模板类
- 这个类的构造函数,参数为一个指针
- 这个类有一个指针变量,用来存储构造函数出过来的指针
- 这个类支持->操作符
- 这个类支持*操作符
- 这个类支持复制操作符
- 这个类析构时要delete管理的指针
- 这个类在复制时,原来的类对象要释放其管理的指针
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <memory> using namespace std; class Monster { public: Monster(){ cout << "Monster construct\n"; }; ~Monster(){ cout << "Monster destruct\n"; }; void doSomething(){ cout << "Monster doSomething\n"; } }; template<typename T> class aauto_ptr { public: //使用explicit关键字避免隐式转换 explicit aauto_ptr(T* p = 0); ~aauto_ptr(); //使用另一个类型兼容的aauto_ptr来初始化一个新的aauto_ptr aauto_ptr(aauto_ptr<T>& rhs); aauto_ptr<T>& operator=(aauto_ptr<T>& rhs); T& operator*() const; T* operator->() const; //返回原始对象的指针 T* get() const; //放弃指针的所以权 T* release(); //删除原有指针并获得指针的p的所有权 void reset(T* p = 0); private: T* pointee; }; template<typename T> aauto_ptr<T>::aauto_ptr(T* p) :pointee(p) {} template<typename T> aauto_ptr<T>::aauto_ptr(aauto_ptr<T>& rhs) : pointee(rhs.release()) {} template<typename T> aauto_ptr<T>::~aauto_ptr() { delete pointee; } template<typename T> aauto_ptr<T>& aauto_ptr<T>::operator=(aauto_ptr<T>& rhs) { if (this != &rhs) reset(rhs.release()); return *this; } template<typename T> T& aauto_ptr<T>::operator*() const { return *pointee; } template<typename T> T* aauto_ptr<T>::operator->() const { return pointee; } template<typename T> T* aauto_ptr<T>::get() const { return pointee; } template<typename T> T* aauto_ptr<T>::release() { T* oldpointee = pointee; pointee = 0; return oldpointee; } template<typename T> void aauto_ptr<T>::reset(T* p) { if (pointee != p) { delete pointee; pointee = p; } } int _tmain(int argc, _TCHAR* argv[]) { aauto_ptr<Monster> monster(new Monster); monster->doSomething(); monster.get()->doSomething(); return 0;; }