共享智能指针

1、std::shared_ptr的初始化

共享智能指针是指多个智能指针可以同时管理同一块有效的内存,共享智能指针shared_ptr是一个模板类,如果要进行初始化有三种方式:通过构造函数、std::make_shared辅助函数以及reset方法。共享智能指针对象初始化完毕后就指向了要管理的那块堆内存,如果想要查看当前有多少智能指针同时管理着这块内存可以使用共享智能指针提供的一个成员函数use_count,函数原型如下:

// 管理当前对象的 shared_ptr 实例数量,或若无被管理对象则为 0。
long use_count() const noexcept;

1.1、通过构造函数初始化

// shared_ptr<T> 类模板中,提供了多种实用的构造函数, 语法格式如下:
std::shared_ptr<T> 智能指针名字(创建堆内存);

测试代码如下:

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

int main()
{
    // 使用智能指针管理一块 int 型的堆内存
    shared_ptr<int> ptr1(new int(520));
    cout << "ptr1.use_count: " << ptr1.use_count() << endl;
    // 使用智能指针管理一块字符数组对应的堆内存
    shared_ptr<char> ptr2(new char[12]);
    cout << "ptr2.use_count: " << ptr2.use_count() << endl;
    // 创建智能指针对象, 不管理任何内存
    shared_ptr<int> ptr3;
    cout << "ptr3.use_count: " << ptr3.use_count() << endl;
    // 创建智能指针对象, 初始化为空
    shared_ptr<int> ptr4(nullptr);
    cout << "ptr4.use_count: " << ptr4.use_count() << endl;

    return 0;
}

测试代码的输出结果:
在这里插入图片描述

注意:如果智能指针被初始化一块有效内存,那么这块内存的引用计数+1,如果智能指针没有被初始化或者被初始化为nullptr空指针,引用计数不会+1,另外,不要使用一个原始指针初始化多个shared_ptr

int *p = new int;
shared_ptr<int> p1(p);
shared_ptr<int> p2(p);		// error, 编译不会报错, 运行会出错,指针p已经初始化了p1了

1.2、通过拷贝和移动构造函数初始化

当一个智能指针被初始化之后,就可以通过这个智能指针初始化其他新对象。在创建新对象的时候,对应的拷贝构造函数或者移动构造函数就可以被自动调用。

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

int main()
{
    // 使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1
    shared_ptr<int> ptr1(new int(520));
    cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;
    //调用拷贝构造函数
    shared_ptr<int> ptr2(ptr1);
    cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;
    shared_ptr<int> ptr3 = ptr1;
    cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;
    //调用移动构造函数
    shared_ptr<int> ptr4(std::move(ptr1));
    cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;
    std::shared_ptr<int> ptr5 = std::move(ptr2);
    cout << "ptr5管理的内存引用计数: " << ptr5.use_count() << endl;

    return 0;
}

测试代码输出的结果:
在这里插入图片描述

注意:如果使用拷贝的方式初始化共享智能指针对象,这两个对象会同时管理同一块堆内存,堆内存对应的引用计数也会增加;如果使用移动的方式初始化智能指针对象,只是转让了内存的所有权,管理内存的对象并不会增加,因此内存引用计数不会变化

1.3、通过std::make_shared初始化

通过C++提供的std::make_shared()就可以完成内存对象的创建并将其初始化给智能指针,函数原型如下:

template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
  • T:模板参数类型。
  • Arg&&…arg:要初始化的数据,如果是通过make_shared创建对象,需要按照构造函数的参数列表指定。

测试代码如下:

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

class Test
{
public:
    Test()
    {
        cout << "construct Test..." << endl;
    }
    Test(int x)
    {
        cout << "construct Test, x = " << x << endl;
    }
    Test(string str)
    {
        cout << "construct Test, str = " << str << endl;
    }
    ~Test()
    {
        cout << "destruct Test ..." << endl;
    }
};

int main()
{
    // 使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1
    shared_ptr<int> ptr1 = make_shared<int>(520);
    cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;
	//使用智能指针管理一块无参Test类类型的内存,内部引用计数为1
    shared_ptr<Test> ptr2 = make_shared<Test>();
    cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;
	//使用智能指针管理一块带有int类型参数的Test类类型的内存,内部引用计数为1
    shared_ptr<Test> ptr3 = make_shared<Test>(520);
    cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;
	//使用智能指针管理一块string类型参数的Test类类型的内存,内部引用计数为1
    shared_ptr<Test> ptr4 = make_shared<Test>("Naruto");
    cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;
    return 0;
}

测试代码的输出结果:
在这里插入图片描述

注意:使用st::make_shared()模板函数可以完成内存地址的创建,并将最终的内存地址传递给共享智能指针对象管理。如果申请的内存是普通类型,通过函数的()可完成地址的初始化,如果要创建一个类对象,函数的()内部需要指定构造函数对象需要的参数,也就是类构造函数的参数,则使用std::make_shared()初始化

1.4、通过reset方法初始化

共享智能指针类提供的std::shared_ptr::reset方法函数原型如下:

void reset() noexcept;

template< class Y >
void reset( Y* ptr );

template< class Y, class Deleter >
void reset( Y* ptr, Deleter d );

template< class Y, class Deleter, class Alloc >
void reset( Y* ptr, Deleter d, Alloc alloc );
  • ptr:指向要取得所有权的对象的指针。
  • d:指向要取得所有权的对象的删除器。
  • aloc:内部存储所用的分配器。

测试代码如下:

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

int main()
{
    // 使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1
    shared_ptr<int> ptr1 = make_shared<int>(520);
    //拷贝赋值,引用计数加1
    shared_ptr<int> ptr2 = ptr1;
    shared_ptr<int> ptr3 = ptr1;
    shared_ptr<int> ptr4 = ptr1;
    cout << "ptr1.use_count: " << ptr1.use_count() << endl;
    cout << "ptr2.use_count: " << ptr2.use_count() << endl;
    cout << "ptr3.use_count: " << ptr3.use_count() << endl;
    cout << "ptr4.use_count: " << ptr4.use_count() << endl;
    cout << endl;
    //释放智能指针指向的内存,清空引用计数
    ptr4.reset();
    cout << "ptr1.use_count: " << ptr1.use_count() << endl;
    cout << "ptr2.use_count: " << ptr2.use_count() << endl;
    cout << "ptr3.use_count: " << ptr3.use_count() << endl;
    cout << "ptr4.use_count: " << ptr4.use_count() << endl;
    cout << endl;
    shared_ptr<int> ptr5;
    //初始化智能指针,引用计数加1
    ptr5.reset(new int(250));
    cout << "ptr5.use_count: " << ptr5.use_count() << endl;

    return 0;
}

测试代码输出结果:
在这里插入图片描述

2、获取原始指针

对应用基础数据类型来说,通过操作智能指针和操作智能指针管理内存效果是一样的,可以直接完成数据的读写。
但是如果共享智能指针管理的是一个对象,那么就需要去除原始内存地址再操作,可以调用共享智能指针类提供的get方法得到原始地址,其函数原型如下:

T* get() const noexcept;

测试代码如下:

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

int main()
{
    int len = 128;
    shared_ptr<char> ptr(new char[len]);
    // 得到指针的原始地址
    char* add = ptr.get();
    //初始化字符串
    memset(add, 0, len);
    //字符串拷贝
    strcpy(add, "I will be Naruto !!!");
    cout << "string: " << add << endl;

    shared_ptr<int> p(new int);
    *p = 100;
    cout << *p.get() << "  " << *p << endl;

    return 0;
}

测试代码的结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值