动态内存与智能指针
来源:互联网 发布:视听语言 知乎 编辑:程序博客网 时间:2024/05/16 14:35
1.为什么会有智能指针?
因为存在下面的一些尴尬情况:
(1)申请动态内存时,new完忘了写delete。如果程序规模比较大,则很难检查出这个错误。导致内存泄露,程序发生莫名其妙的问题。
(2)我们定义a指针指向某对象,然后定义b也指向该对象。此时只是指针的拷贝,对象数据只有一份。当我们通过b释放了该对象时,a指针就变成悬空指针。其危险性和未初始化的指针一样。
(3)避免悬空指针的一个办法是在复制时采用深度复制,即不仅复制指针,而且将指针所指对象也拷贝一个副本。各管各的,互不干扰。但是这样代价太大。
(4)我们希望有一种聪明的指针,可以根据情况自行对上面各种问题作出反应。于是又了智能指针。
2.智能指针的机理
(1)C++98中定义有auto_ptr。C++11中新定义了shared_ptr,unique_ptr,weak_ptr等智能指针。设计采用“引用计数”的方式。即是否释放一个对象,根据是否有指针仍在引用它。如果有则不能释放,如果该对象上的引用计数为0,则系统自动回收。python和java中应该也是这种机理。
(2)于是我们将普通指针包装成一个类。该类中有一个引用计数。并且当新创建时计数为1。当销毁调用析构函数时,或者离开局部作用域时,计数减去1。当复制给另一个指针时,右侧计数加1,左侧计数减去1。这样上面的问题就可解决。
创建一个智能指针a(这里的a是一个智能指针对象)指向某个对象,则计数加1。创建一个b(a),则a,b的计数都将为2,因为giant对象上有2个指针同时指向着。当b=a时,重载=运算符,此时a的计数加1,b的原对象上计数减去1,然后b的计数与a相同。
(3)智能指针的使用,保证系统能够自动回收没人指向的内存,避免内存泄露,把人的因素降到最低。因此《c++ primer》讲到此处作者强烈建议使用智能指针。
3.智能指针实现的示例代码
// shared_ptr.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>using namespace std;//被操作的基础类class Point {public: Point(int xval = 0, int yval = 0) :x(xval), y(yval) {} int getX() const { return x; } int getY() const { return y; } void setX(int xval) { x = xval; } void setY(int yval) { y = yval; }private: int x, y;};//辅助类,每个基础类的对象上都绑定的计数器class refPtr { friend class SmartPtr; refPtr(Point *ptr) :p(ptr), count(1) {} ~refPtr() { delete p; } //计数器 int count; //指向所绑定的基础类的某个对象 Point *p;};//类似shared_ptr的my智能指针类class SmartPtr {public: void print() const { cout << rp->count; } SmartPtr() = default; //当创建一个智能指针,指向基础类的某个对象时 //会调用计数器类的构造函数,生成一个计数器对象绑定到基础类的对象上 //此时智能指针对象->计数器类对象->基础类对象 SmartPtr(Point *ptr) :rp(new refPtr(ptr)) {} //copy constructor //源指针和目的指针,指向同一计数器对象 //把计数器对象中的数+1 SmartPtr(const SmartPtr &sp) :rp(sp.rp) { ++rp->count; } //b=a,拷贝赋值运算符 //首先把右侧指针指向的计数器中的计数+1 //左侧指针指向的计数器中的计数-1,判断是否为0,是则销毁该对象 //让左侧指针指向右侧的计数器 SmartPtr & operator=(const SmartPtr &rhs) { ++rhs.rp->count; if (--rp->count == 0) delete rp; rp = rhs.rp; return *this; } //每个智能指针析构时,都将指向的计数器-1,判断是否需要销毁 ~SmartPtr() { if (--rp->count == 0) delete rp; }private: refPtr *rp;};int main(){ Point a(3, 4); Point * p1 = &a; cout << p1->getX() << endl; SmartPtr p2(p1); p2.print(); //SmartPtr p3(p2); //p2.print(); //p3.print(); return 0;}
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- 动态内存与智能指针
- C++中的动态内存与智能指针
- C++中的动态内存与智能指针
- C++中的动态内存与智能指针
- (十二)动态内存与智能指针
- C++中的动态内存与智能指针
- C++中的动态内存与智能指针
- C++中的动态内存与智能指针
- Error while performing database login with the Mysql connector driver;Unknown database 'test'
- [bzoj3590]SNOI2013 Quare
- AR是什么?能带来哪些黑科技?
- Frogger POJ
- 直方图规定化——Matlab实现及其原理
- 动态内存与智能指针
- LeetCode
- 并发容器
- linux的nohup命令的用法
- vue组件库开发-环境搭建-npm上传
- STL_map
- [日常训练] 藏宝路径
- Sum It Up
- ajax将前台的Map类型数据传到Servlet并解析的方法。