2012-03-03 wcdj
先看一个例子:
#include <iostream>
#include <string>
#include <memory>// auto_ptr class
using std::cout;
using std::endl;
using std::string;
using std::auto_ptr;
void f1()
{
int *ip = new int(123);// dynamically allocate a new object
cout << "&ip = " << ip << "; *ip = " << *ip << endl;
/* code that throws an exception that is not caught inside f1() */
delete ip;
}
void f2()
{
auto_ptr<int> ap(new int(456));// allocate a new object
cout << "&ap = " << &ap << "; *ap = " << *ap << endl;
/* code that throws an exception that is not caught inside f2() */
// auto_ptr freed automatically when function ends
}
void f3()
{
auto_ptr<string> ap_string(new string("delphiwcdj"));
cout << "ap_string = " << *ap_string << endl;
*ap_string = "gerry";
cout << "ap_string = " << *ap_string << endl;
if (ap_string->empty())
{
cout << "ap_string is empty" << endl;
}
else
{
cout << "ap_string is non-empty" << endl;
}
}
int main()
{
cout << "auto_ptr usage\n" << endl;
f1();
f2();
f3();
return 0;
}
/*
g++ -Wall -g -o auto_ptr auto_ptr.cpp
output:
auto_ptr usage
&ip = 0x804b008; *ip = 123
&ap = 0xbfa85d70; *ap = 456
ap_string = delphiwcdj
ap_string = gerry
ap_string is non-empty
*/
标准库的auto_ptr类是接受一个类型参数的模版,它为动态分配的对象提供异常安全。auto_ptr类在头文件memory中定义:
auto_ptr 类 | |
auto_ptr<T> ap; | 创建名为ap的未绑定的auto_ptr对象 |
auto_ptr<T> ap(p); | 创建名为ap的auto_ptr对象,ap拥有指针p指向的对象。该构造函数为explicit |
auto_ptr<T> ap1(ap2); | 创建名为ap1的auto_ptr对象,ap1保存原来存储在ap2中的指针。将所有权转给ap1, ap2成为未绑定的auto_ptr对象 |
ap1 = ap2; | 将所有权从ap2转给ap1。删除ap1指向的对象并且使ap1指向ap2指向的对象,使ap2成为未绑定的 |
~ap | 析构函数。删除ap指向的对象 |
*ap | 返回对ap所绑定的对象的引用 |
ap-> | 返回ap保存的指针 |
ap.reset(p); | 如果p与ap的值不同,则删除ap指向的对象并且将ap绑定到p |
ap.release(); | 返回ap所保存的指针并且使ap成为未绑定的 |
ap.get(); | 返回ap保存的指针 |
注意:
(1) auto_ptr只能用于管理从new返回的一个对象,它不能管理动态分配的数组。当auto_ptr被复制或赋值的时候,有不寻常的行为,因此,不能将auto_ptr存储在标准容器类型中。
(2) auto_ptr对象只能保存一个指向对象的指针,并且不能用于指向动态分配的数组,使用auto_ptr对象指向动态分配的数组会导致未定义的运行时行为。
(3) 每个auto_ptr对象绑定到一个对象或者指向一个对象。当auto_ptr对象指向一个对象的时候,可以说它“拥有”该对象。当auto_ptr对象超出作用域或者另外撤销的时候,就自动回收auto_ptr所指向的动态分配对象。
几点注意事项
1,为异常安全的内存分配使用 auto_ptr
f1()函数中,如果通过常规指针分配内存,此时在执行new和delete之间发生异常,并且该异常不被局部捕获,该内存将不会被回收。
f2()函数中,如果用一个auto_ptr对象来代替,将会自动释放内存,即使提早退出这个块也是这样。编译器保证在展开栈越过f2()函数之前运行auto_ptr对象的析构函数。
2,auto_ptr 是可以保存任何类型指针的模版
auto_ptr<string> ap(new string("My name is delphiwcdj"));
3,将 auto_ptr 绑定到指针
最常见的情况,是将auto_ptr对象初始化为由new表达式返回的对象的地址:
auto_ptr<int> ap(new int(1024));
这个语句将ap初始化为由new表达式创建的对象的地址,这个new表达式将对象初始化为1024。
注意:
接受指针的构造函数为explicit类型的构造函数,所以必须使用初始化的直接形式来创建auto_ptr对象,不能用隐式转换。
auto_ptr<int> ap = new int(1024); // error
auto_ptr<int> ap(new int(1024)); // ok, use direct initialization
4,使用auto_ptr对象
auto_ptr类定义了解引用操作符(*)和箭头操作符(->)的重载版本,因此可以用类似于使用内置指针的方式使用auto_ptr对象:
auto_ptr<string> ap(new string("My name is delphiwcdj"));
*ap = "gerry";// assigns a new value to the object to which ap points
string s = *ap;// initializes s as a copy of the object to which ap points
if (ap -> empty())// runs empty on the string to which ap points
注意:
auto_ptr的主要目的是,在保证自动删除auto_ptr对象引用的对象的同时,支持普通指针式行为。自动删除该对象这一行为导致在怎样复制和访问它们的地址值方面,auto_ptr与普通指针明显不同。
5,auto_ptr对象的复制和赋值是破坏性操作
待续