当前位置: 首页 > news >正文

wordpress回收站在哪里搜索引擎优化关键词的处理

wordpress回收站在哪里,搜索引擎优化关键词的处理,企业做网站的合同,外文网站搭建公司C11之后出现了 shared_ptr 和 unique_ptr,这两个类都是基于RAII技术进行设计的 RAII 利用对象生命周期来控制程序资源(如内存,文件句柄,网络连接,互斥量等资源)的技术,具体地说,就是…

C++11之后出现了 shared_ptr 和 unique_ptr,这两个类都是基于RAII技术进行设计的

RAII

        利用对象生命周期来控制程序资源(如内存,文件句柄,网络连接,互斥量等资源)的技术,具体地说,就是通过构造函数获得资源,通过析构函数释放资源。

RAII的思想需要考虑到一个事实:一个资源不能被释放两次,那么此时如果有两个对象管理同一块资源,这两个对象前后销毁,分别调用析构函数,将导致运行错误。

针对上述可能出现的错误,C++11中有两种方案

方案一

unique_ptr 不允许拷贝或赋值,设计时直接禁用拷贝构造函数和赋值重载函数

unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;

方案二

在有一些场景中,两个智能指针需要管理同一个资源,此时是通过 shared_ptr 进行实现的

shared_ptr 通过引用计数确定管理一块资源的实例化对象的个数。

引用计数达到的效果:只让最后一个管理资源的对象执行释放资源的逻辑

但是,引用计数带来了很多问题,下面将把这些问题提出,并给出shared_ptr解决问题的设计方案

引用计数的设计方案思考

首先,引用计数不能设计成 shared_ptr 的局部私有成员。如果设计成私有成员,拷贝构造和赋值重载改变的时,无法保证旧对象和新对象同时改变引用计数。

其次,引用计数不能设计成全局变量或者静态bianilin,否则在如下场景中 sp1的_pcount和sp2的_pcount的有着相同地址,这是错误的

class A{
public:A(int a1):_a1(a1){}int _a1 = 1;
};int main(){shared_ptr<A> sp1(new A(1));shared_ptr<A> sp2(new A(2));
}

最后,应该设计一个整型指针变量作为引用计数的变量,而且应该在堆上开辟一块空间,不然这个变量的初始化很麻烦

引用计数带来的问题

记 shared_ptr 中引用计数这个成员变量的名称为 _pcount, 即 int* _pcount;

问题一

在多线程场景下,_pcount 作为一个临界资源,应该如何考虑其线程安全问题?

_pcount作为临界资源的场景:

void func(std::shared_ptr<list<int>> sp, int n){for (int i = 0; i < n; i++){std::shared_ptr<list<int>> copy(sp);sp->emplace_back(i);}
}int main(){std::shared_ptr<list<int>> sp1(new list<int>);thread t1(func, sp1, 1000000);thread t2(func, sp1, 2000000);t1.join();t2.join();
}

从如上代码可以看到,t1 和 t2 这两个线程同时进行同时对 sp 进行尾插,

问题二

在调用赋值重载时,应该如何改变旧对象和新对象中的引用计数?(注意需考虑到如下场景)

class A{
public:A(int a):_a(a){}int _a;
};int main(){std::shared_ptr<A> sp1(new A(1));sp1 = sp1;
}

问题三

循环引用场景应该怎么处理?

循环引用场景如下:

struct Node{std::shared_ptr<Node> _next;std::shared_ptr<Node> _prev;int _val;~Node(){/*析构函数调用时的逻辑*/}
};int main(){std::shared_ptr<Node> p1(new Node);std::shared_ptr<Node> p2(new Node);p1->_next = p2;p2->_next = p1;
}

该场景带来的问题描述:

     由于p1->_next的存在,p2 这个对象想要析构,起码要等到 p1 的生命周期结束,因为只有p1的生命周期结束,才会调用其析构函数来释放p1->_next,让引用计数做减减,而由于p2->_next的存在,p1 这个对象想要析构,起码要等到 p2 的生命周期结束,因为只有p2的生命周期结束,才会调用其析构函数来释放p2->_next,
     由此看来,p1 和 p2 都只能等对方先析构才能析构,那么最终的结果会导致这两者都不析构

问题四

shared_ptr所管理的资源释放的方式不同,应该怎么设计,使得不同类型的被管理资源都可以通过对应的释放方式进行释放?

考虑如上问题之后,可以设计出如下的 sharedPtr类

#pragma once
#include <atomic>
#include <functional>
using namespace std;template<class T>
class sharedPtr{
public:sharedPtr(T* sharedptr):_shared_ptr(sharedptr),_pcount(new atomic<int>(1)) // 问题一{}template<class D> // 问题四sharedPtr(T* sharedptr, D delMethod):_shared_ptr(sharedptr),_pcount(new atomic<int>(1)) // 问题一,_del(delMethod){}sharedPtr(const sharedPtr<T>& sp):_shared_ptr(sp._shared_ptr),_pcount(sp._pcount){++(*_pcount);}// 问题二,只有左操作数和右操作数的管理的指针不同才进行引用计数的更改// 旧对象的引用计数减一,减到零就释放sharedPtr<T>& operator=(const sharedPtr<T>& sp) {if (_shared_ptr != sp._shared_ptr) {this->release();_shared_ptr = sp._shared_ptr;_pcount = sp._pcount;++(*_pcount);}return *this;}void release() {if (--(*_pcount) == 0) {_del(_shared_ptr); // 问题四delete _pcount;}}int use_count() {return *_pcount;}T* operator->() {return _shared_ptr;}T& operator*() {return *_shared_ptr;}~sharedPtr() {release();}
private:T* _shared_ptr;atomic<int>* _pcount;// 问题四function<void(T*)> _del = [](T* ptr) {delete ptr; };
};

循环引用的解决方案

从以上的分析可以发现,问题三并没有解决,只能通过weak_ptr进行解决,weak_ptr 不属于RAII技术,创建时不会增加引用计数

make_shared解决的问题

当调用以下代码时

auto ptr = std::shared_ptr<MyClass>(new MyClass(args...));

可能会引起内存碎片,中途异常等问题,因为这句代码会被拆成两句话

MyClass* rawPtr = new MyClass(args...);
auto ptr = std::shared_ptr<MyClass> (rawPtr);

由于引用计数和 MyClass 对象在栈上申请的空间不连续,可能引起内存碎片问题,而MyClass在调用构造函数先开辟空间,开辟空间成功但执行逻辑的过程中如果抛异常,将会导致内存泄漏,make_shared 就解决了这个问题

智能指针的应用

如果出现以下场景,则可以使用智能指针:

需要在栈上开辟一段空间,存放一个自定义类型的结构体

注意:这里不考虑这个自定义类型在调用构造函数时是否需要再在栈上申请一段空间

以下是工厂模式的样例代码

#include <iostream>
#include <string>
#include <memory>class Fruit{
public:Fruit(){}virtual void name() = 0;
};class Apple : public Fruit{
public:Apple(){}void name() override{std::cout << "我是苹果!" << std::endl;}
};class Banana : public Fruit{
public:Banana(){}void name() override{std::cout << "我是香蕉!" << std::endl;}
};class FruitFactory{
public:virtual std::shared_ptr<Fruit> create() = 0;
};class AppleFactory : public FruitFactory{
public:std::shared_ptr<Fruit> create() override{return std::make_shared<Apple>();}
};class BananaFactory : public FruitFactory{
public:std::shared_ptr<Fruit> create() override{return std::make_shared<Banana>();}
};int main(){// 先创建一个一个指向FruitFactory的指针// 虽然这里不能创建抽象类的实例,但是可以创建指向抽象类的指针// 这里创建的是一个指向AppleFactory类型的实例的智能指针对象,这个智能指针的类型是FruitFactory// tmp作为一个类型为FruitFactory的指针,可以触发多态,// 不同类中的create将创建出指向不同类型对象的fruitstd::shared_ptr<FruitFactory> tmp(new AppleFactory());std::shared_ptr<Fruit> fruit = tmp->create();fruit->name();tmp.reset(new BananaFactory());fruit = tmp->create();fruit->name();
}

http://www.yayakq.cn/news/284419/

相关文章:

  • 网站建设的栏目策划app store软件下载
  • 如何看网站的语言企业网站需要什么功能
  • 福建高能建设工程有限公司网站笑话网站模版
  • 自己建一个网站难吗网站备案用的方案建设
  • 阿里云建网站步骤万户网络是干嘛的
  • 公司网站中新闻中心怎样做优化如何进行网络营销
  • 宁波网站模板哪家性价比高上海有名的网站建设公司
  • 怎么开个人网站电影网站怎么做的
  • 修改网站源码连接数据库怎么做自己做的网址如何推广
  • redhat7做网站过程wordpress怎么使用固定连接
  • 东莞高端网站建设费网络推广专员百度百聘
  • 集团网站建设的要求临汾做网站电话
  • 网站报价明细表佛山顺德容桂做网站的公司
  • 做装饰画的行业网站外贸网站推广机构
  • 长沙市网站推广公司上海网络推广团队
  • 做棋牌网站要什么源码山东住房城乡建设厅网站
  • 设计的网站如何做音乐分享类网站
  • 商城网站前台模板免费下载如何注册网页网址
  • 网站建设收费标准效果群晖ds218+做网站
  • h5响应式网站外贸英文网站
  • 嘉兴专业做网站的公司专业网络推广公司
  • 厦门网站做的比较好wordpress去除更新
  • 哪家企业网站做的好国外优秀app设计网站有哪些
  • 网站发帖做业务制作网站能挣钱
  • 做网站微信群凡科建站小程序制作
  • 网站搭建策略与方法是什么绵阳欣城建设
  • 上海网站建设网络公司wordpress 3.9 漏洞
  • 遵义制作公司网站的公司网站展示怎么做
  • 有框架有模板怎么做网站seo自然优化排名
  • 法制教育网站网站 备案 在哪