做网批有专门的网站吗?,中山外贸网站建设公司,吴江seo排名,dw软件做的网站怎么发到网上shared_ptr
shared_ptr继承自__shared_ptr#xff0c;其中有两个对象#xff0c;一个是指向资源的指针#xff0c;一个是控制块#xff0c;指向一个引用计数对象。控制块中存储了强引用和弱引用的计数#xff0c;强引用Uses代表shared_ptr对象的引用计数#xff0c;弱引…shared_ptr
shared_ptr继承自__shared_ptr其中有两个对象一个是指向资源的指针一个是控制块指向一个引用计数对象。控制块中存储了强引用和弱引用的计数强引用Uses代表shared_ptr对象的引用计数弱引用Weaks代表weak_ptr对象的引用计数。 大概结构如上图所示控制块其中也存储了指向资源的指针。 因此在构造一个shared_ptr对象的时候会有两次堆分配一次是为资源分配一次是为控制块分配。因为每一个指向这份资源的指针对象都需要看到同一份引用计数因此跟资源一样也是堆分配的。多次的堆分配和释放也就代表效率上的损失而且极易产生内存碎片。
make_shared
C11同时提供了make_shared函数这是通过构造一个shared_ptr对象而这个对象会事先申请一块足够大的内存空间用于存放管理的资源以及控制块。即分配的堆空间是连续的因此只有一次堆内存分配。 内存的结构就从左边的构造shared_ptr对象到右边的重构对象资源指针和引用计数。 相比shared_ptr构造减少一次内存分配提高效率并且内存空间连续减少内存碎片产生。但是make_shared也存在缺点。
make_shared的缺点
自定义deleter
make_shared在构造智能指针对象的时候不能自定义deleter。在创建对象时同时创建控制块这个控制块内部包含了引用计数、deleter等与管理资源相关的信息。因为资源和控制块是属于同一块申请的内存所以使用自定义deleter可能会导致控制块内存被不正确地释放。因此如果要使用deleter应该使用shared_ptr直接构造。
构造函数
因为make_shared需要用到类的拷贝构造因此需要被管理的类的构造函数是public的。
内存延迟归还
因为分配的空间是连续的在资源指针的Uses变为0之后控制块伴随资源的资源不会被立即释放要等Weak也变为0整块内存才被释放。资源只是被clear但是但是没有归还操作系统。而如果是默认的控制块在资源指针的Uses变为0之后资源会被立即释放内存立即归还。
通过调试看直接构造和make_shared的区别
void test2()
{std::shared_ptrstring p1 std::make_sharedstd::string(10, 9);{std::weak_ptrstd::string wptr1;wptr1 p1;std::shared_ptrstring p2 std::make_sharedstd::string(Hello);wptr1 p2;p2 p1;}std::cout end;
}void test1()
{std::shared_ptrstring p1 std::shared_ptrstd::string(new std::string(10, 9));{std::weak_ptrstd::string wptr1;wptr1 p1;std::shared_ptrstring p2 std::shared_ptrstd::string(new std::string(Hello));wptr1 p2;p2 p1;}std::cout end;
}int main()
{test1();test2();return 0;
}
直接构造
当wptr指向p1的时候可以看到p1的Weaks变为了2weak_ptr观察到的内容与p1一致。并且注意此时control block的value显示为default表示默认的控制块。 当weak_ptr指向p2并且将p2指向p1意思就是p2原来管理的Hello资源要释放掉然后用p1拷贝构造一个对象赋值给p2让p1和p2同时管理10个9。 此时可以看到weak_ptr的资源指针已经显示Error reading说明资源已经释放内存已经归还了。
make_shared构造 此时可以看到原来为default的control block已经改为了make_shared。 重复之前的操作把p2指向p1再看weak_ptr的成员。可以看到ptr指向的资源并没有被释放只是内容并清空而已。只有当weak_ptr的生命周期结束整个内存块才会被释放归还给操作系统。 这就是make_shared最主要的缺点在某些内存要求高的场景下可能不太适用。