C++智能指针

四种auto_ptr、 unique_ptr、 shared_ptr、  weak_ptr。

class base
{
    public:
        void print()
        {
            printf("this is base\n");
        }
}

auto_ptr:

auto_ptr p1(new base());
p1->print();
auto_ptr p2 = p1;//野指针p1产生
p2->print();
p1->print();//错误

auto_ptr会在程序退出的时候进行对象的释放,比我们手动的new和delete方便很多,以上一段代码可以说明问题。auto_ptr指针并不完全安全,当他的对象转移的时候就会产生野指针,也就是控制权进行了转移,当p2=p1时,p1的控制权就已经转移到p2了,p1就成了野指针,当再使用p1 的时候就会报错。

unique_ptr:

unique_ptr p1(new base());
p1->print();
unique_ptr p2=p1;//错误
unique_ptr p3(p1);//错误

这个指针比较自私,一旦使用之后,就会获取所有控制权,不能进行转移,也就是说只能存在一份,不能进行直接构造和直接复制。但是可以移动构造和复制,当然随着移动构造和复制,控制权也要进行转移,也就是说跟auto_ptr是一样的了。

unique_ptr get_ptr()
{
    unique_ptr p1(new base());
    return p1;
}

unique_ptr p2 = get_ptr();//这个地方控制权转移,p1无效,如果p1是个成员变量最好不要这么做,否则会导致p1失效成为野指针,后期再想使用就会出错。

 shared_ptr:

 shared_ptr p1 (new base());//引用计数加1
 p1->print();
 shared_ptr p2=p1;//引用计数加1
 p2->print();
 shared_ptr p3(p1);//引用计数加1
 p3->print();

这个指针使用比较常见。shared_ptr可以多个指针指向同一个对象,在每增加一个shared_ptr的时候,对象的引用计数会自增加1,每当智能指针销毁了,引用计数就减1,当引用计数减少到0的时候就释放引用的对象。每个指针拥有这个对象的所有权,就是说每个指针都可以单独的使用里面的变量。特别注意shared_ptr不能循环使用,即:

class A
{
    public:
        shared_ptr p;
}

class B
{
    public:
        shared_ptr p;
}

shared_ptr pA(new A);
shared_ptr pB(new B);
pA->p = pB;
pB->p = pA;

weak_ptr:

weak_ptr是shared_ptr的延申,一般与shared_ptr一起使用,主要是为了防止循环引用导致的内存泄漏问题。weak_ptr不会拥有对象的所有权,而且他还不能直接使用他所引用的对象,也不会增加对象的引用计数。当weak_ptr转换成shared_ptr的时候才会拥有所有权(使用weak_ptr的lock()方式进行转换),转换后weak_ptr的引用计数增加1。如果对象销毁,weak_ptr无效,即指向空。

void Function()
{
 shared_ptr sp( new int(10) );
 assert(sp.use_count() == 1);
 weak_ptr wp(sp); //从shared_ptr创建weak_ptr
 assert(wp.use_count() == 1);
 if (!wp.expired())//判断weak_ptr观察的对象是否失效
 {
  shared_ptr sp2 = wp.lock();//获得一个shared_ptr
  *sp2 = 100;
  assert(wp.use_count() == 2);
 }
 assert(wp.use_count() == 1);
 return 0;
}

总结:
1. 尽量使用unique_ptr而不要使用auto_ptr
2. 一般来说shared_ptr能够满足我们大部分的需求
3. weak_ptr可以避免递归的依赖关系

你可能感兴趣的:(base,C++,smart_ptr)