c11---智能指针

2 篇文章 0 订阅

目录

为什么需要智能指针?

内存泄露

RALL

裸指针的问题 

智能指针有哪些 

unique_ptr(唯一性智能指针)

创建模式:

定义唯一性智能指针

出现错误

唯一性智能指针管理资源

 const的修饰作用

模板的特化 

总结:

注:多学一点

 bool强转

const构成重载:const修饰*p

 移动构造

new int (10)所做的四件事

this指针---为什么函数里面需要this指针?

.和->的区别

创建对象

 仿函数

new和malloc的区别

c++系统自动给出的函数有

delete和delete[ ]区别何在

小tips


为什么需要智能指针?

内存泄露

c++中没有内存回收,需要程序员自己使用delete,而智能指针就很好地解决了这个问题,可以自动正确地销毁动态创建的对象,防止内存泄漏

RALL

充分地利用了c++语言局部对象自动销毁的特性来控制资源(内存heap、网络套接字、互斥量,文件句柄等)的生命周期

 RALL过程中的四个步骤

  1. 设计一个类封装资源
  2. 在构造函数中初始化
  3. 在析构函数中执行销毁操作
  4. 使用时定义一个该类的局部对象

裸指针的问题 

  1. 很难区分指针的指向是单个对象还是一组对象
  2. 使用完成后不好判断该不该销毁指针
  3. 销毁的方式不同,例如是delete还是fclose
  4. 是delete还是delete[ ]
  5. 由于是手动调用delete,万一多调用了或者少调用了,还是会出现内存泄漏问题
  6. 没有办法分辨指针是否处于悬挂状态,即delete了指针但是并没有让它指向nullptr

智能指针有哪些 

auto_ptr,unique_ptr,shared_ptr,weak_ptr

unique_ptr(唯一性智能指针)

特点:

  1. 一个指针只能指向一个资源,即一块资源不能被两个指针指向
  2. unique_ptr具有唯一性(即特点一中所指的特性),所以不提供构造函数和左值构造函数重载。
  3. 提供移动构造移动赋值函数
  4. 为了实现单个对象和一组对象的管理添加了删除器类型
  5. 在容器保存指针是安全的
  6. unique_ptr具有->和*运算符重载,因此它可以像普通指针一样使用

创建模式:

如何来创建这个unique_ptr呢?先来引入一个头文件

#include<memory>//内存管理
int main()

{
	std::unique_ptr<int> ip(new int(10));//持有了堆区的资源
	*ip = 100;
	cout << *ip << endl;
}

    unique_ptr不用delete释放空间,系统自动调用析构函数释放空间

资源都是new出来的(堆区资源) 

注意:unique_ptr是释放堆区的资源!

class Int
{
private:
 int value;
public:
 Int(int x = 0) :value(x) { cout << "Create Int" << this << endl; }
 ~Int() { cout << "Destroy Int: " << this << endl; }
 Int(const Int& it) :value(it.value) { cout << "Copy Create Int: " << this << endl; }
 Int& operator=(const Int& it)
 {
  if (this != &it)
  {
   value = it.value;
  }
  cout << this << " operator=()" << &it << endl;
  return *this;
 }
 //void SetValue(int x) { value = x; }  
 //int GetValue() const  { return value; }
 int& Value() { return value; }
 const int& Value() const { return value; }
};
template<class _Ty>
class my_unique_ptr
{
private:
 _Ty * ptr;
public:
 //typedef _Ty element_type;
 //typedef _Ty* pointer;
 using element_type = _Ty;
 using pointer = _Ty*;
public:
 explicit my_unique_ptr(pointer p = nullptr) :ptr(p) {}
 ~my_unique_ptr() 
 {
  if (nullptr != ptr)
  {
   reset();//释放资源
  }
 }  // delete ptr ; free(ptr);

 //pointer get(my_unique_ptr * const this)
 pointer get() const
 {
  return this->ptr;
 }
 //_Ty & operator*(my_unique_ptr * const this)
 _Ty & operator*() const
 {
  return *this->get();  // return get(this);
 }  // *ip = 100;   operator*(&ip) = 100;
 pointer operator->() const
 {
  return get();
 }
 pointer release()
 {
  pointer old = ptr;
  ptr = nullptr;
  return old;
 }
 void reset(pointer p = nullptr)
 {
  if (ptr != nullptr)
  {
   delete ptr;
  }
  ptr = p;
 }

 //void swap(const my_unique_ptr* const this, my_unique_ptr& other);
 void swap(my_unique_ptr& other)
 {
  //this = nullptr; error
  std::swap(this->ptr, other.ptr);
 }  // ip.swap(sp); // swap(&ip,sp);

};
void funa()
{
 my_unique_ptr<Int> sp(new Int(10));
 my_unique_ptr<Int> ip(new Int(20));
 my_unique_ptr<Int> ap;
 ap = ip;
}

定义唯一性智能指针


 my_unique_ptr<Int> sp(new Int(10));
 my_unique_ptr<Int> ip(new Int(20));
 my_unique_ptr<Int> ap;
 ap = ip;

出现错误

ap和ip指向同一个地址,但是一个资源只能由一个智能指针进行管理,而不能有多个智能指针管理一个资源。

唯一性智能指针管理资源

要使得unique_ptr指针具有通用性,例如在文件的打开、关闭中,文件资源的管理是不一样的,要想保证unique_ptr的通用性,对特殊类型的资源管理,就自己重写删除器的类型。

整个程序的构建都是为了通用!!!(出现在人工智能)

 const的修饰作用

	//pointer get(my_unique_ptr * const this)
	pointer get() const
	{
		return this->ptr;
	}

模板的特化 

 调用情况

总结:

unique_ptr相比较于裸指针的特性

  1. 可以解决悬空指针或多次删除被指向对象
  2. 解决资源泄露问题
  3. 通常用来确保指针寿命和其指向对象寿命一致

注:多学一点

 bool强转

可以将变量变为bool类型,在if语句中可以判断

operator bool() const
{
    return (ptr !=nullptr);
}

const构成重载:const修饰*p

void func(int *p){}
void func(const int* p){}

 移动构造

my_unique_ptr(const my_unique_ptr&& x)
{
    ptr = x.ptr;
    x.ptr = nullptr;
}

拷贝构造和移动构造同时书写了,那么就会调用移动构造

new int (10)所做的四件事

1.计算10的大小 2.malloc 3.赋值 4.返回所在地址

new没有能力去构造对象 

is具有常性,不可以对is的指向进行修改。

const修饰*is,is的指向可以修改

 

this指针---为什么函数里面需要this指针?

  1. 创建对象类型有多个,方法共享只有一个,用this来调用函数方法
  2. 系统是面向过程编程,底层把面向对象编程变为面向过程的体系

类的成员函数都含有this指针,只有static,友元,全局没有this指针。

.和->的区别

  .  的时候函数都是智能指针的方法

 -> 的时候函数都是 类 类 型 的方法

创建对象

std::unique_ptr<Int> ip(new(10));

std::unique_ptr<Int> sp=new Int(100);

 仿函数

struct ADD
{
	int operator()(int a, int b) const//仿函数()
	{
		return a + b;
	}
};

int main()
{
	ADD add;
	int x = add(12, 23);//调用仿函数
	//标准c++没有三元仿函数
	x = add.operator()(12, 23);//把括号当成函数名了
}

new和malloc的区别

  1. 失败处理方式不同,new会抛出异常,malloc不会
  2. new有构造函数予以赋值
  3. new有重载运算符

c++系统自动给出的函数有

  •  缺省的构造
  • 缺省的拷贝构造
  • 缺省的析构
  • 缺省的赋值

 !!!以上四个必须有

delete和delete[ ]区别何在

int main()
{
    Int* p=new Int(10);
    Int*s =new Int[10];

    delete p;
    delete[]s;
    return 0;
}

检查有没有析构函数

小tips

写代码判断是否相等时得把常量放在左边,变量放在右边

explict外部

内存泄漏的本质:丢失了内存地址

不能重载的运算符:?:::*.

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值