C++学习--动态内存

序言

大家五一快乐呀!!有几天没有写了,今天刚好回学校有空,就写写东西吧。

今天学习的是动态内存和智能指针。

1、C++内存

我学习的资料中是这样定义C++内存分配的,可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。

静态内存

静态内存用来保存局部static对象、类static数据对象以及定义在任何函数外的变量。在使用之前分配,在程序结束之后销毁。

栈内存

在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

堆内存(动态内存)

除了静态内存和栈内存,每个程序有个内存池。这部分叫做自由内存或堆。程序用堆来动态分配的对象。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。

接下来介绍分两大类,1、动态内存管理(new和delete);2、智能指针

2、动态内存管理(new和delete)

C++定义两个运算符来分配和释放内存。运算符new分配内存,delete释放new分配的内存。(好像还有malloc和free,后面我在学习一下。)

new

在自由空间中分配的内存是无名的,所以new不能对其分配的内存命名,而是返回一个指向该对象的指针:

        int *p = new int;  //pi指向一个动态分配的、未初始化的内存的无名对象

*动态分配的对象是默认初始化的,所以对于内置类型或组合类型的对象的值将是未定义的;对于类 类型,将是默认构造函数进行初始化;同时,我们可以直接初始化或者列表初始化。

        int *pi =new int(1024);

        string *ps =new string()//初始化为空的string,因为是类类型。

delete

我们传递给delete的指针必须是指向动态分配的内存或者空指针,不允许释放并非new分配的内存或者释放多次。这些行为都是未定义的;

我们要记住动态对象的生存期直到被释放(delete)为止

delete之后要重置指针值,当我们delete一个指针之后,指针值变得无效。虽然指针失效了,但是很多机器上的指针仍然指向保存着动态内存的地址,就变成了空悬指针,即指向一块曾经保存数据对象但是现在已经无效的内存的指针,类似未初始化的指针

        int *p(new int()42);

        delete p;

        p =nullptr;

3、智能指针

上述动态内存的使用很容易出问题,因为确保在正确的时间的释放内存是非常困难的。忘记释放内存就会产生内存泄漏。

为了更容易也更安全的使用动态内存,标准库提供了两种智能指针shared_ptr和unique_ptr,与常规指针的区别在于它负责自动释放所指向的对象

智能指针都允许的操作:

  1. shared_ptr<T> sp
  2. unique_ptr<T> up
  3. p :这个一般作为条件判断,如果指向对象,则为true;
  4. *p:解引用
  5. p->mem:等价于(*p).mem
  6. p.get():返回p保存的指针.不过要小心使用,如果智能指针释放了其对象,返回的指针所指的对象就消失了
  7. swap(p,q)和p.swap(p):交换指针

shared_ptr

shared_ptr允许有多个指针指向一个对象,当最后一个指针被销毁的时候,指向的对象也会被销毁.

shared_ptr独有的操作:

  1. make_shared<T> (args):返回一个shared_ptr,指向动态分配的对象
  2. shared_ptr<T>p(q):拷贝初始化:这个操作会递增q中的计数器.
  3. p =q:p的计数会减1,q的计数会加1;p如果计数为0,销毁
  4. p.use_count():返回与p共享对象的指针数.
  5. p.unique():判断是否只有一个指针指向对象,即use_count为1
  6. p.reset(new int(1024)):我们可以用这个给shared_ptr赋予一个新指针

shared_ptr的拷贝和赋值都会引起引用计数的变化.

最安全分配动态内存就是用make_shared(),这个类似顺序容器的emplace成员

        shared_ptr<T> p = make_shared<T>(args);通常用auto

        shared_ptr<T> p (new T(args));

shared_ptr不仅会自动销毁所管理的对象,还会自动释放相关联的内存

unique_ptr

与shared_ptr不一样,某个时刻只能有一个unique_ptr指向一个给定的对象,unique_ptr没有类型make_shared的函数,所以定义一个unique_ptr需要绑定到new返回的指针上。且与shared_ptr一样只能直接初始化。

  1. unique_ptr的操作:
  2. unique_ptr<T> u1:空unique_ptr,u1会使用delete释放指针
  3. unique_ptr<T,D> u2:u2会使用可调用对象来释放指针
  4. u =nullptr:释放指向的对象,将u置空
  5. u.release() :u放弃对指针的控制权,返回指针,并将u置空
  6. u.reset(q):令u指向内置指针q

注:虽然我们不能拷贝unique_ptr,但是可以拷贝和赋值一个将要被销毁的unique_ptr

unique_ptr<int> clone(int p){
    return unique_ptr<int>(new int(p));
}

weak_ptr

weak_ptr是一种不控制所指对象生存期的智能指针,他指向一个由shared_ptr管理的对象。weak_ptr绑定到一个shared_ptr上,不会引起计数的变化。所以weak_ptr抓住了智能指针“弱”共享对象的特点。

weak_ptr的操作

  1. weak_ptr<T> w:空weak_ptr,指向类型为T的对象
  2. weak_ptr<T> w(sp):与shared_ptr绑定,指向同一个对象的weak_ptr
  3. w=p:p可以是weak_ptr,也可以是shared_ptr,赋值后共享对象
  4. w.reset()//w.reset(p):重置
  5. w.use_count():与w共享对象的shared_ptr的数量
  6. w.expired():如果use_count返回的是0,这个返回true
  7. w.lock():如果expired返回true,返回一个空的shared_ ptr;否则返回一个指向w的对象的shared_ptr

也就是说weak_ptr可以不影响shared_ptr所指对象的生存期,共享对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值