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

企业门户定制网站建设公司磁力搜索器下载

企业门户定制网站建设公司,磁力搜索器下载,政府网站wap门户建设方案,车辆租赁的网站建设智能指针(1) 概念内存泄漏指针指针概念RAII使用裸指针存在的问题 智能指针使用分类unique(唯一性智能指针)介绍智能指针的仿写代码理解删除器 概念 内存泄漏 内存泄漏:程序中已动态分配的堆内存由于某些原因而未释放…

智能指针(1)

  • 概念
    • 内存泄漏
    • 指针指针概念
    • RAII
    • 使用裸指针存在的问题
  • 智能指针使用
    • 分类
    • unique(唯一性智能指针)
      • 介绍
      • 智能指针的仿写
      • 代码理解
      • 删除器

概念

内存泄漏

内存泄漏:程序中已动态分配的堆内存由于某些原因而未释放或无法释放,导致程序运行速度减慢甚至崩溃。
内存泄漏分为两类:

  • 堆内存泄漏:在堆区申请了资源,结束时候没有将其堆区进行释放,导致该内存无法再次被使用。(或者说指向堆区内存的指针丢失)
  • 资源泄漏:通常指系统资源,比如套接字,文件描述符等,因为这些在系统中都是有限制的,如果创建了而不归还,长时间就会耗尽资源,导致其他程序不可用。(例如:创建文件文件描述符(打开文件),但不归还(不关闭文件))。

指针指针概念

在java和C#语言中都有自动的垃圾回收机制,系统可以自动释放资源,为此在这些语言中,内存管理都不是问题。
C++中没有 垃圾回收机制,必须自动取释放资源,否则就会出现内存泄漏,因为在开发中内存泄漏很容易出现,但是又必须耗费大量精力去寻找解决内存泄漏,所以出现了智能指针。

int main() {int* ip=new int(10);if(ip!=nullptr) {//.....}//因为代码处理复杂,忘记释放return 0;
}

如上面就会出现内存泄漏,而解决内存泄漏最有效的方法就是指针指针。
智能指针:智能指针就是一个对象,智能指针对象中有一个指针,该指针存储的动态动态船舰对象的地址,用于生存期的控制,能够确保指针指针在对象离开作用域是自动调用析构函数来销毁对象(释放内存),防止内存泄漏。使用了智能指针就不会担心内存泄漏的问题了,也不需要手动释放内存了。

RAII

RAII是资源获取即初始化,使局部对象来管理资源的技术称为资源获取即初始化。
改方法就是充分利用了C++局部对象自动销毁的特性来控制资源的生命周期。
这些资源主要指操作系统中内存,套接字等,局部对象是指存储在栈中的对象,其生命周期靠操作系统来管理,无需人工介入。
RAII过程四个步骤:

  • 设计一个类封装资源。
  • 在构造函数中初始化。
  • 在析构函数中执行销毁操作。
  • 使用时定义一个类的局部对象。
class Object {int* ip;
public:Object(int val = 0) {ip = new int(val);cout << "create obj" << endl;}~Object() {delete ip;cout << "destory obj" << endl;}
};
void func() {Object obj(3);return;
}
int main() {func();return 0;
}

在func函数中创建了obj对象,obj也就是局部对象,在函数结束时,系统会自动释放销毁对象,也就自动调用了obj对象的析构函数。为此我们在使用资源的时候,在构造函数中进行初始化,在析构函数中进行销毁。

使用裸指针存在的问题

  • 难以区分指针指向的是单一对象还是一组对象
  • 使用完无法判断是否应该销毁对象,因为无法判断是否拥有指向的对象。(销毁之后仍然指向堆内存,但是堆内存已经释放)
  • 在已经确定了销毁指针的情况下,也无法确定是用那个关键字来删除,例如delete,fopen等
  • 即使确定了销毁指针的方法,也无法判断删除的对象是一组还是一个(delete,delete[])
  • 上面问题就算都解决了,也难以保证在代码所有执行路径中有且只有一次销毁指针。
  • 理论上没有办法来分辨一个指针是否处于悬挂状态。

智能指针使用

分类

C++11提供了4钟智能指针:auto_ptr,unique_ptr,shared_ptr和weak_ptr.
使用时需要引入头文件:#include < memory >
因为auto_ptr时C98标准中的,C98中没有右值引用,也没有move和forward,为此已经被C++11所弃用,所有此处不做过多介绍。
智能指针主要应用于多线程问题,因为在多线程中自主控制释放极为复杂,智能指针可以在线程结束时自动释放该对象的资源。

unique(唯一性智能指针)

介绍

我们以自定义的int类型指针为例:

int main() {unique_ptr<PtrInt> pa(new PtrInt(10));pa->Print();pa->SetValue(200);pa->Print();return 0;
}

我们创建了唯一性指针对象pa,指向船舰的PtrInt对象,可以通过指针来调用类的成员方法。并且会自动析构。
错误使用

my_unique_ptr<PtrInt> pa3(new PtrInt(3));//A
int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));PtrInt p(1);my_unique_ptr<PtrInt> pa1(&p);//BPtrInt* ip = new PtrInt(2);my_unique_ptr<PtrInt> pa2(ip);//C
}

A:使用智能指针管理全局变量是没有意义的,因为程序结束后,指针才销毁,都不如直接定义一个全局变量,其会在程序结束时自动销毁。(智能指针主要依赖局部对象来释放)
B:对象本身就是在栈中,而智能指针是处理堆区堆存,所以是错误的。
C:该方法本质上不是错误的,因为你用了裸指针,如果发现用了指针还没释放,就会释放两次,导致程序崩溃。
而这个唯一性指针是怎么实现的呢?

智能指针的仿写

template<class _Tp>
struct my_default_deleter
{void operator()(_Tp* ptr)const {delete ptr;}
};
template<class _Tp>
struct my_default_deleter<_Tp[]>
{void operator()(_Tp* ptr)const {delete []ptr;}
};
struct FileDeleter {void operator()(FILE* pf) const {fclose(pf);}};
template<class _Tp,class _Dp=my_default_deleter<_Tp>> 
//template<class _Tp,class _Dp>
class my_unique_ptr//<_Tp[],_Dp>
{ 
public:using pointer = _Tp*;using elemtype_type = _Tp;using deleter_type = _Dp;
private:_Tp* ptr;deleter_type mDeleter;
public:/*deleter_type get_deleter()const {return mDeleter;}*/my_unique_ptr(_Tp* p = nullptr) :ptr(p) { cout << "create myuniqueptr" << endl; }//构造函数~my_unique_ptr() {//析构mDeleter(ptr);//mDeleter.operator()(ptr);//get_deleter()(ptr);ptr = nullptr;cout << "deatory myuniqueptr" << endl;}my_unique_ptr(const my_unique_ptr&) = delete;//删除拷贝构造my_unique_ptr& operator=(const my_unique_ptr&) = delete;//删除左值赋值重载my_unique_ptr(my_unique_ptr&& right) :ptr(right.ptr) {//移动构造right.ptr = nullptr;cout << "move create myuniqueptr" << endl;}my_unique_ptr& operator=(my_unique_ptr&& right) {//右值赋值重载if (this == &right) return *this;reset(right.release());//首先返回参数对象的资源指针,然后用该指针指向的资源代替现有指针的资源return *this;}pointer get() const { return ptr; }//返回指针_Tp& operator*()const { return *get(); }//指针解引用pointer operator->()const { return get(); }//指向符号重载pointer release() {//资源返回,将指向资源的指针返回pointer p = ptr;ptr = nullptr;return p;}void reset(pointer p = nullptr) {//资源移动,将形参指针指向的资源覆盖掉原本的资源,释放原本资源。mDeleter(ptr);ptr = p;}void swap(my_unique_ptr& u) {//交换指针指向的资源std::swap(this->ptr, u.ptr);}operator bool() const {//判断是否指向有效空间return get() != nullptr?true:false;}
};

上面就是指针指针的仿写,下面是使用
指向符重载,解引用:可以看出智能指针在这一块的使用和裸指针相同

int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));(*pa).SetValue(100);(*pa).Print();pa->SetValue(200);pa->Print();//pa.operator->()->Print();此处系统省去了一个指向符。return 0;
}

reset函数和release函数
release():返回指针
reset():资源覆盖,释放原本资源

int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));pa->Print();pa.reset(new PtrInt(100));//用新资源覆盖旧资源pa->Print();
}
int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));PtrInt* p = pa.get();//获取了指针,delete p;//errorPtrInt* ip = pa.release();//直接将指针指向nullptr,并且将指向资源的指针返回。
}

swap()函数:智能交换具名对象

int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));my_unique_ptr<PtrInt> pb(new PtrInt(20));pa->Print();pb->Print();pa.swap(pb);//只能和具名对象进行交换pa->Print();pb->Print();return 0;
}

判空
判断指针是否为nullptr

int main() {unique_ptr<PtrInt> pa(new PtrInt(10));unique_ptr<PtrInt> pb(new PtrInt(20));my_unique_ptr<PtrInt> pc;if (pc) {//判断是否指向有效空间pc->Print();}
}

移动拷贝,移动赋值,拷贝构造,赋值重载
因为赋值重载和拷贝构造都是默认的浅拷贝,所以会出现两个指针指向同一资源,导致释放两次出现错误,所以呢删除了系统默认的拷贝构造函数和赋值重载。
而移动构造和移动赋值是可以实现的。这也就是唯一性智能指针的特点,有且只能管理一份资源。

int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));//my_unique_ptr<PtrInt> pb(pa);//浅拷贝 errormy_unique_ptr<PtrInt> pb(new PtrInt(20));//pa = pb;//浅拷贝 errmy_unique_ptr<PtrInt> pc(std::move(pa));pa = std::move(pb);return 0;
}

代码理解

my_unique_ptr<PtrInt> func(int x) {my_unique_ptr<PtrInt> pa(new PtrInt(x));return pa;
}
int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));pa = func(100);return 0;
}

首先在主函数中创建了只能指针对象,然后在func函数中船舰了智能指针的另一个对象,函数结束时使用移动构造来构建一个将亡值对象,然后移动赋值给pa对象。
在这里插入图片描述

void func(my_unique_ptr<PtrInt> px) {
}
int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));func(std::move(pa));pa->Print();return 0;
}

该程序会崩掉,因为把pa的资源移动到了px参数中,不存在拷贝构造,所以程序会因为pa指向为nullptr而崩掉。

void func(my_unique_ptr<PtrInt>& px) {px->Print();px->SetValue(200);px->Print();px.release();//my_unique_ptr<PtrInt> pb(std::move(px));
}
int main() {my_unique_ptr<PtrInt> pa(new PtrInt(10));func(pa);pa->Print();//errorreturn 0;
}

不能用移动语义接收智能指针,可以通过引用来接收智能指针,但不要在函数内部让让智能指针的资源移动走,否则智能指针指向nullptr。唯一性指针智能控制一个对象的资源。

删除器

在上面代码仿写中仿写了删除器,主要是为了使程序可用性更高,用到了仿函数,大家可以看一看以前的文章理解一下。

int main() {my_unique_ptr<FILE,FileDeleter> pfile(fopen("D:/tulun/ConsoleApplication6/ConsoleApplication6.cpp", "w"));//D:\tulun\ConsoleApplication6\ConsoleApplication6.cppreturn 0;
}

结果如下:

在这里插入图片描述

http://www.tj-hxxt.cn/news/57181.html

相关文章:

  • 网站开发域名网站推广怎样做
  • 工商局网站清算组备案怎么做域名批量查询
  • 广州的做淘宝女鞋货源下载数据包的网站网址是多少?百度网址导航主页
  • 可以做笔记的网站上海百度竞价托管
  • 资源网站排名优化seo百度免费推广有哪些方式
  • 新建的网站怎么做seo优化推广普通话宣传周
  • 上海哪家公司提供专业的网站建设成都网站建设技术支持
  • 做网站必须要公司才能做吗seo是什么简称
  • html在线编写网站seo排名影响因素主要有
  • 西安培训网站建设互联网营销行业前景
  • 重庆市城市建设档案馆网站丁的老头seo博客
  • 芜湖做网站的客户排名优化seo公司
  • 网站数据库是什么推广普通话手抄报内容
  • 做律师网站公司免费制作永久个人网站
  • 地方门户网站源码发布友情链接
  • 唐山制作网站的预测2025年网络营销的发展
  • 做网站比较好的软件整站优化关键词推广
  • 网站开发怎么接入支付宝腾讯广告平台
  • 成品网站w灬 源码1688三叶草爱网站查询挖掘工具
  • wordpress 数字指纹怎样给自己的网站做优化
  • 招聘网站开发费用手机网页设计制作网站
  • 娄底网站优化一键识图找原图
  • 网站建设南京公司网站建设地推接单平台
  • 做定制型网站百度主页网址
  • 做首饰网站百度网址大全在哪里找
  • 公司网站公司网站软文是什么东西
  • 保定网站建设公司seo优化工具有哪些
  • 营销型网站有那些网站1688精品货源网站入口
  • 政府蒙古文网站建设汇报材料中国站长工具
  • 深圳网站优化网站市场调研报告3000字范文