智能指针auto_prt(C++98)
auto_ptr 是 c++ 98 定义的智能指针模板,其定义了管理指针的对象,可以将new 获得(直接或间接)的地址赋给这种对象。当对象过期时,其析构函数将使
用 delete 来释放内存!
1、用法
头文件:
#include
用 法:
auto_ptr<类型> 变量名(new 类型)
#include <iostream>
#include <string>
#include <exception>
#include <memory>
using namespace std;
//auto_ptr< Test> t(new Test()); //忠告 1: 智能指针不要定义为全局变量
class Test
{
public:
Test() {
cout << "Test is construct" << endl;
debug = 1;
}
~Test() {
cout << "Test is destruct" << endl;
}
int getDebug() {
return debug;
}
private:
int debug;
};
//用 法: auto_ptr<类型> 变量名(new 类型)
void memory_leak_demo1() {
auto_ptr< Test> t(new Test());
//忠告 3: 除非自己知道后果,不要把 auto_ptr 智能指针赋值给同类型的另外一个智能指针
auto_ptr< Test> t1;
t1 = t;
auto_ptr<Test>* tp = new auto_ptr<Test>(new Test()); //忠告 2: 不要定义指向智能指针对象的指针变量
//在使用智能指针访问对象时,使用方式和普通指针一样
cout<< "-> debug: "<<t->getDebug()<< endl;
cout << "* debug: " << (*t).getDebug() << endl;
Test* tmp = t.get();//获取到自己指向的位置给新的指针
cout << "get debug: " << tmp->getDebug() << endl;
//release 取消指针指针对动态内存的托管,之前分配的内存必须手动释放
Test* tmp = t.release();
delete tmp;
//reset 重置智能指针托管的内存地址,如果地址不一致,原来的会被析构掉
t.reset();
t.reset(new Test());
if(0){
Test* t1 = new Test();
t1->getDebug();
}
return;
}
int memory_leak_demo2() {
//Test* t = new Test();
auto_ptr< Test> t(new Test());
{
throw exception("文件不存在");
}
//delete t;
return 0;
}
int main()
{
memory_leak_demo1();
/*try {
memory_leak_demo2();
}catch (exception e) {
cout << "catch exception: " << e.what() << endl;
}*/
system("pause");
return 0;
}
2、建议
1.尽可能不要将 auto_ptr 变量定义为全局变量或指针
2.除非自己知道后果,不要把 auto_ptr 智能指针赋值给同类型的另外一个智能指针
3.C++11 后 auto_ptr 已经被“抛弃”,已使用 unique_ptr 替代!
3、auto_prt弊端
auto_ptr 基于排他所有权模式:两个指针不能指向同一个资源,主要问题:
1、复制或赋值都会改变资源的所有权
2、在 STL 容器中使用 auto_ptr 存在重大风险,因为容器内的元素必需支持可复制(copyconstructable)和可赋值(assignable)。
3、不支持对象数组的内存管理
#include <stdio.h>
#include <iostream>
#include <string>
#include <memory>
#include <vector>
using namespace std;
int main() {
//弊端 1. auto_ptr 被 C++11 抛弃的主要理由 p1= p2 ,复制或赋值都会改变资源的所有权
auto_ptr<string> p1(new string("I 'm martin."));
auto_ptr<string> p2(new string("I 'm rock."));
printf("p1: %p\n", p1.get());
printf("p2: %p\n", p2.get());
p1 = p2;
printf("after p1 = p2\n");
printf("p1: %p\n", p1.get());//p1为p2的值,之前值被delete
printf("p2: %p\n", p2.get());//p2为0000000
//弊端 2. 在 STL 容器中使用 auto_ptr 存在重大风险,因为容器内的元素必需支持可复制(copy
constructable)和可赋值(assignable)。
vector<auto_ptr<string>> va;
auto_ptr<string> p3(new string("I 'm p3."));
auto_ptr<string> p4(new string("I 'm p4."));
va.push_back(std::move(p3));//不支持左值,用move变成右值
va.push_back(std::move(p4));
cout <<"va[0]: "<< *va[0] << endl;
cout <<"va[1]: "<< *va[1] << endl;
//风险来啦
va[0] = va[1];
cout << "va[0]: " << *va[0] << endl;
cout << "va[1]: " << *va[1] << endl;
//弊端 3. 不支持对象数组的内存管理
//auto_ptr<int[]> ai(new int[5]); //不能这样定义
//auto_ptr 陷阱,不能把同一段内存交给多个 auto_ptr 变量去管理
/*{
auto_ptr<string> p2;
string* str = new string("智能指针的内存管理陷阱");
p2.reset(str);
{
auto_ptr<string> p1;
p1.reset(str);
}
cout <<"str: " << *p2 << endl;
}*/
system("pause");
return 0;
}