C ++ auto_ptr smart pointer analysis

Background:

  RAll mechanism

  Define a class of resources to allocate and free the package, to complete the allocation and initialization of resources in the constructor, complete clean up resources in the destructor to ensure proper initialization and cleanup resources

ps: smart pointer is an application RAll mechanism, smart pointer is an object fundamentally


What 1.auto_ptr that?

auto_ptr class template is a C ++ standard library, by initializing an auto_ptr pointing created by the new dynamic memory , it is the owner of this memory, a memory can not be allocated to the two owners , when the end of the life cycle of an auto_ptr that an auto_ptr destructor will automatically release has dynamic memory, even if an abnormality occurs, the abnormality can also stack deployment release dynamic memory, auto_ptr does not support the new array

ps: header: #include <Memory>


2. Initialize method auto_ptr

1) Constructor

The normal pointer points to an existing dynamic memory is configured as a parameter

int *p=new int(33);

auto_ptr<int> aptr(p);

Direct construction

auto_ptr<int> aptr(new int(33));

2) Copy constructor

The use of smart pointers that already exist to construct a new smart pointer

auto_ptr<string> p1(new string("name"));
auto_ptr<string> p2(p1);

Note: Because a dynamic memory can only be exclusive of a smart pointer, so the transfer of ownership will take place during the copy constructor and assignment, the copy constructor in this process, p1 will lose ownership of a string of memory, and p2 obtained objects when destroyed, p2 responsible for memory automatically destroyed

3) Assignment

The use of smart pointers that already exist to construct a new smart pointer

auto_ptr<string> p1(new string("name"));
auto_ptr<string> p2(new string("sex"));

p1=p2;

Before the assignment is deleted by the object pointed to p1, p1 have sex after a string of memory assigned ownership, p2 sex is no longer used to point to a string object

ps: directly define an empty smart pointers, the default value is 0


3.防止两个auto_ptr对象拥有同一个对象(同一块内存)

因为auto_ptr的内存所有权是独占的,所以以下代码存在问题

int *p=new int(10);

auto_ptr<string> p1(p);
auto_ptr<string> p2(p);

因为p1和p2都认为p是由它管,在析构时都试图删除p,两次删除同一个对象的行为在C++标准中是未定义的,我们必须防止这样使用auto_ptr


4.警惕auto_ptr作为参数

1)按值传递时,函数的调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr(拷贝构造),这样传入的实参就其对原对象的所有权,而该对象在函数退出时会被局部的auto_ptr删除,样例如下:

void f(auto_ptr<int> aptr)
{
    cout<<*aptr<<endl;
}
int main()
{
    auto_ptr<int> aptr(new int(10));
    f(aptr);
    cout<<*aptr<<endl;//错误,经过f函数调用,原有的aptr已经不再拥有任何对象了

}

2)参数为引用或指针,虽然不会存在上述的拷贝过程,但是我们并不知道函数对传入的auto_ptr做了什么,如果其中的某种操作使其失去了对象的所有权,那么还是会导致致命的执行错误

结论:const reference是auto_ptr作为参数传递的底线


5.auto_ptr不能初始化为指向非动态内存

因为delete表达式被应用在指向非动态内存的指针上,这是C++未定义的程序行为


6.auto_ptr常用的成员函数

1)get:返回auto_ptr指向的那个对象的内存地址

int main()
{
    int *p=new int(10);
    cout << "the adress of p: "<< p << endl;

    auto_ptr<int> aptr(p);

    cout << "the adress of aptr: " << &aptr << endl;
    cout << "the adress of the object which aptr point to: " << aptr.get() << endl;

}

/*
程序运行结果:
the adress of p: 0xb50f80
the adress of aptr: 0x69fed8
the adress of the object which aptr point to: 0xb50f80
*/

2)reset:重新设置auto_ptr指向的对象,类似于赋值操作,但是赋值操作不允许将一个普通指针直接赋值给auto_ptr,而reset允许

reset(0)可以释放对象,销毁内存

int main()
{
    auto_ptr<string> aptr(new string("name"));
    aptr.reset(new string("sex"));

    cout<<*(aptr.get())<<endl;
    cout<<*aptr<<endl;
}
/*
程序运行结果:
sex
sex
*/

3)release:返回auto_ptr指向的那个对象的内存地址,并且释放这个对象的所有权

用此函数初始化auto_ptr可以避免两个auto_ptr对象指向同一个对象的情况

int main()
{
    auto_ptr<string> aptr(new string("name"));

    auto_ptr<string> aptr1(aptr.get());//这是两个auto_ptr拥有同一个对象
    auto_ptr<string> aptr2(aptr.release());//release可以先释放所有权,这样就不会指向同一个对象
}

该函数不会释放对象,仅仅会归还所有权


7.千万不要把auto_ptr对象放在容器中

容器要求对象可以进行安全的赋值操作,可以将一个对象拷贝到另外一个对象,从而获得两个独立的逻辑上相同的拷贝,尤其是当一个对象被拷贝到另外一个对象后,原来的对象不会改变,但是很显然,auto_ptr不支持这个性质


使用总结:

1)两个auto_ptr对象不会同时指向同一个内存,要明白两个auto_ptr对象赋值会发生什么

2)auto_ptr对象存储的指针应该为NULL或者指向一个动态内存块

3)auto_ptr对象存储的指针应该指向单一物件(是new出来的,而不是new[]出来的,不支持指向指针数组)

4)千万不要把auto_ptr对象放在容器中

5)当将auto_ptr作为参数传递时,const reference是auto_ptr作为参数传递的底线


结论:使用一个auto_ptr的限制很多,还不能用来管理堆内存数组,使用不当会引发很多的问题,其中一些设计也不符合C++设计的思想,所以产生了boost的智能指针,boost的智能指针可以解决上面的问题!下节将讨论boost智能指针


Guess you like

Origin www.cnblogs.com/yinbiao/p/11540743.html