C++--智能指针简单解析及用法

本文介绍四种智能指针,
auto_ptr(C++11已弃用)、unique_ptr、shared_ptr 和 weak_ptr
智能指针作用:帮助管理资源,避免内存泄漏

auto_ptr(C++11已弃用)

虽然已弃用,但仍可使用。
先看例子

#include <iostream>
#include <memory>
using namespace std;

class myPoint{
public:
    myPoint(int a)
    {
        cout << "myPoint的有参构造" << endl;
    }
    ~myPoint()
    {
        cout << "myPoint的析构" << endl;
    }

    void print_out()
    {
        cout << Print_content << endl;
    }

    string Print_content;
};

void example()
{
    auto_ptr<myPoint> au_smart(new myPoint(1));//利用智能指针创建一个新的对象

    if(au_smart.get()) //如果智能指针不为空
    {
        au_smart.get()->Print_content = "hello!";
        au_smart->print_out();
    }
}

int main()
{
    example();
    return 0;
}

使用auto_ptr需要先包含memory头文件,可以通过get()获得裸指针。
从上面可以看出,我们并不用delete new 出来的myPoint了
有以下注意事项:

#include <iostream>
#include <memory>
using namespace std;

class myPoint{
public:
    myPoint(int a)
    {
        cout << "myPoint的有参构造" << endl;
    }
    ~myPoint()
    {
        cout << "myPoint的析构" << endl;
    }

    void print_out()
    {
        cout << Print_content << endl;
    }

    string Print_content;
};

void example1()
{
    auto_ptr<myPoint> au_smart1(new myPoint(1));
    if(au_smart1.get())
    {
        au_smart1.get()->Print_content = "haha";
        auto_ptr<myPoint> au_smart2;
        au_smart2 = au_smart1;//au_smart2 获得au_smart1管理的内存的所有权,au_smart1失去所有权

        au_smart2->print_out();
        au_smart1->print_out();
    }
}

int main()
{
    example1();
    return 0;
}

上面这个例子编译能通过,但是运行的时候会崩溃,原因在使用
au_smart2 = au_smart1;
的时候,au_smart2已经指向au_smart1指向的地址,并且获得所有权,au_smart1无权再访问它原本所指向的内存,所以au_smart1再想访问对象的成员函数时候,就会崩溃。
如果想提前手动释放auto_ptr管理的内存,有如下方式

void example2()
{
    auto_ptr<myPoint> au_smart(new myPoint(1));
    if(au_smart.get())
    {
        delete au_smart.release();;
    }
}

void example3()
{
    auto_ptr<myPoint> au_smart(new myPoint(1));
    if(au_smart.get())
    {
        myPoint * temp = au_smart.release();//release不会释放对象,归还所有权
        delete temp;
    }
}
//reset()方法:如果不传递参数或传递NULL,则智能指针会释放内存。
//   如果传递的是一个对象,则智能指针会释放当前对象,从而管理传递进来的对象
void example4()
{
    auto_ptr<myPoint> au_smart(new myPoint(1));
    if(au_smart.get())
    {
        au_smart.reset();//使用reset方法释放内存
    }
}

shared_ptr

shared_ptr提供一个 use_count() 指针计数功能,每被引用一次,use_count()返回值+1,使用完成一次,use_count()返回值-1
shared_ptr可以使用 * 的方式获取裸指针,可以使用 get() 方法获取裸指针,或者直接使用 -> 去访问对象内容

#include <memory>
#include <iostream>
using namespace std;

class myPoint{
public:
    myPoint(int a)
    {
        cout << "myPoint的有参构造" << endl;
    }
    ~myPoint()
    {
        cout << "myPoint的析构" << endl;
    }

    void print_out()
    {
        cout << Print_content << endl;
    }

    string Print_content;
};

void Testshare_pointer(shared_ptr<myPoint> a)
{
    a->print_out();
    cout << "shared_ptr use:" << a.use_count() << endl;//每使用一次引用次数+1
}

void example()
{
   shared_ptr<myPoint> shared_smart(new myPoint(1));

   if(shared_smart.get())
   {
        shared_smart.get()->Print_content = "haha";
        shared_smart->print_out();
   }
   cout << "shared_ptr use:" << shared_smart.use_count() << endl;
   Testshare_pointer(shared_smart);
   cout << "shared_ptr use:" << shared_smart.use_count() << endl;//在上面函数结束后,引用次数-1
}

int main()
{
    example();
    return 0;
}

上例输出结果:

	 myPoint的有参构造
 	 haha
	 shared_ptr use:1
	 haha
	 shared_ptr use:2
     shared_ptr use:1
     myPoint的析构

在上述例子中,未拷贝shared_smart前,shared_smart的引用次数为1,在传进Testshare_pointer后,shared_smart的引用次数+1,当Testshare_pointer结束后,
shared_smart的引用次数-1。
shared_ptr的最佳应用场合顾名思义即是我们需要共享某对象的时候就使用它,还可以使用use_count()查看当前对象引用次数,非常方便管理

weak_ptr

weak_ptr一般与shared_ptr搭配使用,shared_ptr可以直接赋值给weak_ptr,但是shared_ptr的引用计数并不会增加,所以它的用处可以是对shared_ptr进行观察。
如基类定义一个weak_ptr用于指向子类的shared_ptr,基类可通过观察自身weak_ptr就可以知道子类是否对自身进行操作,便于管理对象

#include <memory>
#include <iostream>
using namespace std;

class myPoint{
public:
    myPoint(int a)
    {
        cout << "myPoint的有参构造" << endl;
    }
    ~myPoint()
    {
        cout << "myPoint的析构" << endl;
    }

    void print_out()
    {
        cout << Print_content << endl;
    }

    string Print_content;
};

void example()
{
    shared_ptr<myPoint> shared_smart(new myPoint(1));
    weak_ptr<myPoint> weak_smart;

    cout << "shared_ptr use:" << shared_smart.use_count() << endl;
    weak_smart = shared_smart;
    cout << "shared_ptr use:" << shared_smart.use_count() << endl;
}

int main()
{
    example();
    return 0;
}

输出结果:
myPoint的有参构造
shared_ptr use:1
shared_ptr use:1
myPoint的析构
可以看出当weak_smart 指向shared_smart后,shared_smart的引用次数并没有增加。

unique_ptr

unique_ptr可以说是弃用auto_ptr的代替品,unique顾名思义某个时刻只能有一个unique_ptr指向一个给定对象,当unique_ptr被销毁时,对象也被销毁。

#include <memory>
#include <iostream>
using namespace std;

class myPoint{
public:
    myPoint(int a)
    {
        cout << "myPoint的有参构造" << endl;
    }
    ~myPoint()
    {
        cout << "myPoint的析构" << endl;
    }

    void print_out()
    {
        cout << Print_content << endl;
    }

    string Print_content;
};

void example()
{
     unique_ptr<myPoint> unique_smart1(new myPoint(1));
     cout << "Before transform: " << endl;
     cout << "unique_smart1 address: " << unique_smart1.get() << endl;
     unique_ptr<myPoint> unique_smart2;
     cout << "unique_smart2 address: " << unique_smart2.get() << endl;

     cout << endl;
     cout << "After transform: " << endl;
     unique_smart2 = move(unique_smart1);
     cout << "unique_smart1 address: " << unique_smart1.get() << endl;
     cout << "unique_smart2 address: " << unique_smart2.get() << endl;
}


int main()
{
    example();
    return 0;
}

输出结果:

	myPoint的有参构造
	Before transform:
	unique_smart1 address: 0x7ab698
	unique_smart2 address: 0
	
	After transform:
	unique_smart1 address: 0
	unique_smart2 address: 0x7ab698
	myPoint的析构

一个时刻只能有一个unique_ptr指向一个给定对象,所以当unique_smart1使用move()方法之后,unique_smart1立刻被销毁,从结果可以看到unique_smart1的地址指向了0,unique_smart2指向了unique_smart1原本指向的地址

发布了20 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43086497/article/details/105299408