标签:
1, auto_ptr类 auto_ptr是一个模板类,定义如下: template <typename Type> class auto_ptr {...}; 它存储的是一个指向Type的指针。 顾名思义,auto_ptr是一种智能指针,它包含一个动态分配内存的指针,并在它生命周期结束的时候,销毁包含的指针所指向的内存。 例1: void f() { Type* pt(new Type); //一些代码... delete pt; } 这样的代码很常见,但它有可能造成内存泄露。首先你用了new,你就要记得用delete,但即使你记住了用delete,还是会出问题。如果f()在执行delete pt之前,就抛出了异常,函数返回了。那么这个分配的对象就没被删除。 使用auto_ptr,很优雅的解决了这些问题。 例2: void f() { auto_ptr<Type> pt(new Type); //一些代码... } 现在的代码,不会泄露Type类型的对象。不管是函数正常结束,还是抛出异常结束,都会调用pt的析构函数,从而删除分配的对象。 2, auto_ptr构造函数 构造函数1:explicit auto_ptr(Type* _Ptr = 0) throw( ); auto_ptr<int> pt; //包含一个int*的指针,并初始化为NULL auto_ptr<int> pt(new int(123)); //包含一个int*的指针,并初始化为123的地址 auto_ptr<int> pt = new int(123); //error!构造函数声明为explicit 构造函数2:auto_ptr(auto_ptr<Type>& _Right) throw( ); int* ptr = new int(); auto_ptr<int> pt1(ptr); //构造函数1 auto_ptr<int> pt2(pt1); //将pt1的使用权转给pt2,注意pt1指向NULL了 //pt1调用了本身的release()函数,将内部指针地址传给pt2 构造函数3:template<typename Other> auto_ptr(auto_ptr<Other>& _Right) throw( ); 声明这样一个拷贝构造函数的目的,就是为了派生类指针能转换成基类的指针。 例: class Base { }; class Derived : public Base { }; auto_ptr<Derived> pDerived(new Derived); auto_ptr<Base> pBase(pDerived); //让这样的代码能通过编译器 其本质是为了让,auto_ptr类内部的Derived*转换为Base* 构造函数4:auto_ptr(auto_ptr_ref<Type> _Right) throw( ); //暂略 3, auto_ptr成员函数 成员函数1:Type* get( ) const throw( ); 获得包含指针的地址 int* ptr = new int(123); auto_ptr<int> pt(ptr); assert(pt.get() == ptr); //相等,指向同一地址 成员函数2:Type* release( ) throw( ); 返回包含指针的地址,并将包含指针设为NUll string* pstr = new string("hello"); auto_ptr<string> pt(pstr); pt.release(); //不在指向string对象 //此时,pt.get()等于NULL delete pstr; //应该手动删除pstr指向的内存块 成员函数3:void reset(Type* _Ptr = 0); double* pdouble1 = new double(3.14); double* pdouble2 = new double(1.23); auto_ptr<double> pt1(pdouble1); pt1.reset(pdouble2); //将删除pt1所指向的内存块就是pdouble1指向的那块 //此时,pt.get()等于pdouble2 cout << *pdouble1; //error,pdouble已经是野指针了。 4, 使用总结 1,auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。 2,auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。 3,两个auto_ptr对象不会同时指向同一块内存块。要明白2个auto_ptr对象赋值会发生什么。 4,千万不要把auto_ptr对象放在容器中。 5,当将auto_ptr作为函数参数时,最好声明为const auto_ptr<T>&(by const ref).当函数返回值可以简单的传值(by value).
转载自:http://blog.csdn.net/just_a_beginning/article/details/4386755
#include <iostream> #include <memory> int main() { double* pd = new double(77.77); std::cout << "*pd = " << *pd << std::endl; std::cout << "pd = " << pd << std::endl; // std::auto_ptr<double> apd = pd; // 接受指针的构造函数是explicit构造函数, 所以隐式初始化是不允许的. std::auto_ptr<double> apd(pd); std::cout << "*apd = " << *apd << std::endl; // std::cout << "apd = " << apd << std::endl; // 直接使用auto_ptr对象取地址是错误的. std::cout << "apd.get() = " << apd.get() << std::endl; // 应该使用auto_ptr对象的get成员方法返回auto_ptr对象中的基础指针. 注意: 不是 apd->get() . int* pi = new int(7); std::auto_ptr<int> api_1(pi); // std::auto_ptr<int> api_2(api_1.get()); // 不能用get方法作为创建其它auto_ptr对象的实参. std::auto_ptr<int> api_2(api_1); // api_1成为了未绑定的auto_ptr对象, api_2指向了pi. // std::cout << "*api_1 = " << *api_1 << std::endl; // 对未绑定的auto_ptr对象解引用, 其效果与对未绑定的指针解引用相同: 程序出错并且没有定义会发生什么. std::cout << "*api_2 = " << *api_2 << std::endl; float* pf = new float( static_cast<float>(0.77) ); // 0.77是double类型, 强转下. std::auto_ptr<float> apf; // apf = pf; // 与内置指针不同, 不能直接将一个地址(或其它指针)赋给auto_ptr对象. apf.reset(pf); // 只能调用reset方法来改变指针. std::cout << "*apf = " << *apf << std::endl; apf.reset(0); // 复位auto_ptr对象, 传0给reset方法即可. apf变成了未绑定的auto_ptr对象. return 0; } //我的编译器运行出现错误‘reset‘ : is not a member of ‘auto_ptr<float>‘ //vc 6.0对标准的支持不好,可以用VS来运行。
转载自:http://blog.csdn.net/g5dsk/article/details/4815495
标签:
原文地址:http://www.cnblogs.com/leijiangtao/p/4671968.html