<一>智能指针基础
代码1
int main(){
//裸指针,手动开辟,需要自己释放,如果忘记了或者因为
//程序逻辑导致p没有释放,那么就会导致内存泄漏
int *p=new int(10);
if(***){
retur -1;
}
delete p;
return 0;
}
有没有什么办法帮我们管理指针,确保资源释放?
智能指针
利用栈上的对象出作用域时自动析构的特征,来做到资源的自动释放
问题:是否可以在堆上创建裸指针?语法上没有问题,但是我们正式希望
栈上对象出作用域能自动析构的特征来达到自动管理指针的目的,如果
将智能指针创建在堆上,那又和原来的裸指针使用遇到的问题是一样的了
需要手动delete
代码2
#include <iostream>
using namespace std;
template<typename T>
class MySmartPtr1 {
public:
MySmartPtr1(T * ptr=nullptr) : _mptr(ptr) { }
~MySmartPtr1() {
delete _mptr;
_mptr = nullptr;
}
T & operator*() { return *_mptr; }//返回的 是 & , 需要修改值
T * operator->() { return _mptr; }
private:
T * _mptr;
};
int main() {
MySmartPtr1<int> ptr(new int(10));
*ptr= 200;
return 0;
}
代码2的问题
int main() {
MySmartPtr1<int> ptr(new int(10));
//使用ptr 拷贝构造ptr2,默认的拷贝构造方式是值拷贝,所以底层
//_mptr指针 指向的是同一块内存,那么ptr2 和ptr析构的时候就会有问题了,两次析构同一片内存
MySmartPtr1<int> ptr2(ptr);
*mptr = 200;
return 0;
}
如何解决呢?
1:不带引用计数的智能指针
auto_ptr C++库提供
C++11 新标准
scoped_ptr
unique_ptr
代码 关于 auto_ptr
int main() {
auto_ptr<int> ptr1(new int(100));
auto_ptr<int> ptr2(ptr1);
*ptr2 = 200;
cout<<*ptr1<<endl;//执行报错,原因见下图
return 0;
}
现在不推荐使用auto_ptr
容器中推荐用auto_ptr吗? vector<auto_ptr> v1; v2(v1); 容器的拷贝构造和容器的赋值容易引起容器元素的拷贝构造和赋值,而auto_ptr的拷贝构造会将原来管理的底层资源(指针)置空
代码关于 scoped_ptr
int main() {
scope_ptr的处理方式
scope_ptr<int>(const scope_ptr<int> & src)=delete;//通过直接和谐掉这两个方法
scope_ptr<int> & operator=(const scope_ptr<int> & src))=delete;//通过直接和谐掉这两个方法
return 0;
}
所以scoped_ptr使用的也很少
代码关于 unique_ptr
int main() {
unique_ptr的处理方式
unique_ptr<int>(const unique_ptr<int> & src)=delete;//通过直接和谐掉这两个方法
unique_ptr<int> & operator=(const unique_ptr<int> & src))=delete;//通过直接和谐掉这两个方法
unique_ptr<int> ptr1(new int(100));
unique_ptr<int> ptr2(ptr1);//编译报错,尝试使用已经删除的函数, 要改成如下!!!
unique_ptr<int> ptr1(new int(100));
unique_ptr<int> ptr2(std::move(ptr1));//编译OK,为什么可以呢?因为unique_ptr提供了右值引用的拷贝构造和右值引用的赋值函数,如下
unique_ptr<int>(const unique_ptr<int> && src){};
unique_ptr<int> & operator=(const unique_ptr<int> && src)){};
return 0;
}
//推荐使用
2:带引用计数的智能指针(share_ptr,weak_ptr)
带引用计数的好处:多个智能指针可以管理同一个资源
带引用计数:给每一个对象资源,匹配一个引用计数,
智能指针引用一个资源的时候,给这个资源引用计数加1
当这个智能指针出作用域不再使用资源的时候,给这个资源引用计数-1,当引用计数不为0的时候,还不能析构这个资源,
当引用计数为0的时候,说明已经没有外部资源使用这个资源了,那么就可以析构这个资源了
代码3 简单实现share_ptr
#include <iostream>
using namespace std;
template<typename T>
class RefCount {
public:
RefCount(T * pSrc = nullptr, int refCount = 0):_pSrc(pSrc),_refCount(refCount) {
}
void addCount() { this->_refCount++; }
void deleltCount() { --this->_refCount; }
int refCount() { return this->_refCount; }
private:
T * _pSrc;
int _refCount = 0;
};
template<typename T>
class MySmartPtr2 {
public:
//新创建的智能指针,默认计数器为1
MySmartPtr2<T> (T * mptr=nullptr): _mptr(mptr){
_pRef = new RefCount<T>(_mptr,1);
}
//拷贝构造
MySmartPtr2<T>(const MySmartPtr2<T> & _rval) {
//两个智能指针指向相同的资源
this->_mptr = _rval._mptr;
this->_pRef = _rval._pRef;
this->_pRef->addCount();
}
//赋值重载
MySmartPtr2<T> & operator=(const MySmartPtr2<T> & _rval) {
if (this == &_rval) { retur *this; }
else {
this->_pRef->deleltCount();
int currentCount = this->_pRef->refCount();
if (currentCount == 0) {
delete this->_mptr;//销毁指向的资源
this->_mptr = nullptr;
delete _pRef;
_rPef = nullptr;
}
this->_pRef = _rval._pRef;
this->_mptr = _rval._mptr;
this->_pRef->addCount();
return *this;
}
}
~MySmartPtr2<T>() {
this->_pRef->deleltCount();
int currentCount = this->_pRef->refCount();
if (currentCount == 0) {
delete this->_mptr;//销毁指向的资源
this->_mptr = nullptr;
delete _pRef;
_pRef = nullptr;
}
}
int getRefCount() { return this->_pRef->refCount(); }
private:
T * _mptr;
RefCount<T> * _pRef;
};
int main() {
MySmartPtr2<int> ms1(new int(100)) ;
{
MySmartPtr2<int> ms2(ms1);
cout << "RefCount=" << ms1.getRefCount() << endl;
MySmartPtr2<int> ms3(ms1);
cout << "RefCount=" << ms1.getRefCount() << endl;
}
cout << "RefCount=" << ms1.getRefCount() << endl;
system("pause");
return 0;
}
share_ptr: 强智能指针,可以改变资源的引用计数
weak_ptr: 弱智能指针,不会改变资源的引用计数
强智能指针:循环引用(交叉引用)是什么问题?什么结果?怎么解决?
交叉引用代码
class A{
pubic:
A(){cout<<"A()"<<endl;}
~A(){cou<<"~A()"<<endl;}
share_ptr<B> _ptrb;
}
class B{
pubic:
B(){cout<<"B()"<<endl;}
~B(){cou<<"~B()"<<endl;}
share_ptr<A> _ptrb;
}
int main(){
share_ptr<A> pa(new A());
share_ptr<B> pb(new B());
pa->_ptrb=pb;
pb->_ptra=pa;
cout<<pa.use_count()<<endl;// 2
cout<<pb.use_count()<<endl;// 2
}
上面代码造成new出来的资源无法释放!!资源泄漏问题
解决:
定义对象的时候,用强智能指针,引用对象的地方用弱智能指针
class A{
pubic:
A(){cout<<"A()"<<endl;}
~A(){cou<<"~A()"<<endl;}
void testA(){
cout<<"A testA() Function"<<endl;
}
weak_ptr<B> _ptrb;
}
class B{
pubic:
B(){cout<<"B()"<<endl;}
~B(){cou<<"~B()"<<endl;}
void function(){
share_ptr<A> _tp=_ptrb.lock();//提升方法
if(_tp!=nullptr){
_tp->testA();
}
}
weak_ptr<A> _ptrb; //weak_ptr 弱智能指针,不会改变引用计数
}
int main(){
share_ptr<A> pa(new A());
share_ptr<B> pb(new B());
pa->_ptrb=pb;
pb->_ptra=pa;
pb.function();
cout<<pa.use_count()<<endl;// 2
cout<<pb.use_count()<<endl;// 2
}
share_ptr 和 weak_ptr 是线程安全的.
<一>智能指针基础的更多相关文章
- Boost智能指针-基础知识
简单介绍 内存管理一直是 C++ 一个比較繁琐的问题,而智能指针却能够非常好的解决问题,在初始化时就已经预定了删除.排解了后顾之忧.1998年修订的第一版C++标准仅仅提供了一种智能指针:std::a ...
- C++ 中的智能指针-基础
简介 在现代 C++ 编程中,标准库包含了智能指针(Smart pointers). 智能指针用来确保程序不会出现内存和资源的泄漏,并且是"异常安全"(exception-safe ...
- C++ 基础知识回顾(string基础、智能指针、迭代器、容器类)
[1] string基础 [1.1] string 的构造 #include <iostream> #include <string> int main() { using n ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针]
[易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针] 实用知识 智能指针 我们今天来讲讲Rust中的智能指针. 什么是指针? 在Rust,指针(普通指针),就是保存内存地址的值 ...
- c++基础 使用智能指针
三个智能指针模板(auto_ptr.unique_ptr和shard_ptr)都定义了类似指针的对象(c++11已将auto_ptr摒弃),可以将new获得(直接或间接) 的地址赋给这种对象.当智能指 ...
- ndk学习之c++语言基础复习----C++线程与智能指针
线程 线程,有时被称为轻量进程,是程序执行的最小单元. C++11线程: 我们知道平常谈C++线程相关的东东基本都是基于之后要学习的posix相关的,其实在C++11有自己新式创建线程的方法,所以先来 ...
- C++基础--智能指针
智能指针其实也不是完全的指针,应该说是像指针一样的类对象,智能指针通常有指针的功能,当然同时也包含了一些额外的功能.目前比较常见的智能指针有auto_ptr.unique_ptr和shared_ptr ...
- 【UE4 C++ 基础知识】<15> 智能指针 TSharedPtr、UniquePtr、TWeakPtr、TSharedRef
基本概念 UE4 对 UObject 对象提供垃圾回收 UE4 对原生对象不提供垃圾回收,需要手动进行清理 方式 malloc / free new / delete new与malloc的区别在于, ...
- C++智能指针
引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...
- C++ 引用计数技术及智能指针的简单实现
一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...
随机推荐
- 关于在PyCharm中使用虚拟环境
Python虚拟环境的概念对于管理项目用到的第三方包真是好处多多,所以也想在PyCharm使用虚拟环境. 在这个过程中,遇到很多问题: 第一是使用Python创建虚拟环境,然后在PyCharm创建项目 ...
- win7通过netsh命令禁用、启用本地连接 定时关闭开启网络连接
1) 先检查网络接口名称 C:\Windows\system32>netsh interface show interface 管理员状态 状态 类型 接口名称 ---------------- ...
- 使用cnpm创建vue项目(含离线安装)
# 全局安装淘宝cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org #升级 npm cnpm install npm ...
- Git Review + Gerrit 安装及使用完成 Code-Review
转载自:https://cloud.tencent.com/developer/article/1010615 1.Code Review 介绍 Code Review 代码评审是指在软件开发过程中, ...
- Hbase之理论
第1章 HBase简介 1.1 什么是HBase HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Hadoop的子项目来开发维护,用于支持结构化的数据存储. 官方 ...
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(29)-Fiddler如何抓取Android7.0以上的Https包-终篇
1.简介 上一篇宏哥介绍的Xposed是一款可以在不修改APK的情况下影响程序运行的框架.可以编写并加载自己编写的插件app,实现对目标apk的注入.拦截等.一般研究移动安全的都会使用Xposed. ...
- app自动化测试环境安装
一.环境依赖 app自动化测试环境如下: appium服务 第三方库appium-python-client 手机或模拟器 java环境jdk1.8 android环境 二.appium服务安装 1. ...
- Codeforces Round #829 (Div. 1/Div. 2) 1753 A B C D 题解
Div1A / 2C. Make Nonzero Sum 令最后每个\(a_i\)的系数为\(c_i\)(\(c_i=1/-1\)),发现只要满足\(c_1=1\)(下标从1开始),且c中没有两个-1 ...
- python关于Django搭建简单博客项目(详解一)
上一篇我们说了如何搭建简易博客网站,下面我们来进行详细解答.本文没有特定顺序,请结合上一篇和源代码参照学习. 相关源代码和解析请参看:https://github.com/Cheng0829/mysi ...
- Windows7下驱动开发与调试体系构建——2.R3与R0的通信示例
目录/参考资料:https://www.cnblogs.com/railgunRG/p/14412321.html 在阅读本节前,建议先阅读<Windows内核安全与驱动开发>第五章内容, ...