<一>智能指针基础
代码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.智能指针是什么 简单来说,智能指针是一个类,它对普 ...
随机推荐
- Pod 使用进阶
静态 Pod 在 Kubernetes 集群中除了我们经常使用到的普通的 Pod 外,还有一种特殊的 Pod,叫做Static Pod,也就是我们说的静态 Pod,静态 Pod 有什么特殊的地方呢? ...
- 持续集成指南:GitLab 的 CI/CD 工具配置与使用
前言 写代码这项工作,本质就是将工作自动化,减少手工操作提供效率,因为人的本质都是懒狗,程序员也不能例外,为了各种意义的效率提升(懒),我们需要持续集成工具,将代码测试.编译.发布这些重复性很高的工作 ...
- Future详解
Future模式 [1]Future模式是多线程开发中常见的设计模式,它的核心思想是异步调用.对于Future模式来说,它无法立即返回你需要的数据,但是它会返回一个契约,将来你可以凭借这个契约去获取你 ...
- Oracle字段约束
初识约束 约束是数据库用来确保数据满足业务规则的手段,对数据做的条件限制. 约束的类型 1. 主键约束(PRIMARY KEY) 2. 唯一性约束(UNIQUE) 3. 非空约束(NOT NULL) ...
- 20220728 - DP训练 #1
20220728 - DP训练 #1 时间记录 \(8:00-9:00\) T1 尝试做 \(T1\),可惜并未做出,没有想到是资源分配 设置三维状态,初值一直不知道怎么设置 并且对于距离有一部分不会 ...
- 字符串匹配(BF算法和KMP算法及改进KMP算法)
#include <stdio.h> #include <string.h> #include <stdlib.h> #include<cstring> ...
- SQL中的转义字符和通配符
一.通配符 如果想查找"_cs"结尾的的账户 select * from [user] where loginname like '%_cs'是不行的, _ 被认为是任意的字 ...
- raid 5搭建部署
raid 5搭建部署 软raid与备份 1.用四块磁盘做实验,三块盘搭建raid阵列组,有一块当作备份可以使用raid 5来搭建三块磁盘的阵列组 创建命令如下: [root@xiaohaoge ~]# ...
- java代码整洁之道
package Day01;import org.junit.Test;import java.text.NumberFormat;import java.util.Scanner;public cl ...
- 你不知道的React Developer Tools,20 分钟带你掌握 9 个 React 组件调试技巧
壹 ❀ 引 React Developer Tools 是 React 官方推出的开发者插件,可以毫不夸张的说,它在我们日常组件开发中,对于组件属性以及文件定位,props 排查等等场景都扮演者至关重 ...