c++基础(六)——动态内存
在我们的程序中,静态内存——用来保存局部 static 对象,类 static数据成员,以及定义在任何函数之外的变量。栈内存——用来保存定义在函数内的非 static 对象。分配在 静态内存 或 栈内存中的对象由编译器自动创建和销毁。对于栈内存,仅在其定义的程序块运行时才存在,static对象在使用之前分配,在程序结束时销毁。
除此之外,每个程序还拥有一个内存池,这部分内存被称为自由空间(堆),程序用堆来存储动态分配的对象,——即那些在程序运行时分配的对象。
1. 动态内存和智能指针
在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;delete,接受一个动态指针,销毁该对象,并释放与之关联的内存。
新的标准提供了两种智能指针(smart pointer)类型来管理动态对象。shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象。标准库还定义了一个名为weak_ptr的伴随类,指向shared_ptr所管理的对象。这三种类型都定义在memory中。
1.1 share_ptr 类
类似vector智能指针也是模板。
shared_ptr<string> p1; //shared_ptr,可以指向string
shared_ptr<list<int>> p2; //shared_ptr,可以指向int的list
智能指针的使用方法和普通指针类似,解引用返回它指向的对象,如果在一个条件判断中使用智能指针,效果就是检测它是否为空,
// 如果 p1 不为空,检查它是否指向一个空 string
if (p1 && p1->empty()) // p->mem -- (*p).mem
*p1 = "ds"
1.2 make_shared 函数
最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数。此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。与智能指针一样,make_shared也定义在memory中。
//指向一个值为42的int的shared_ptr
shared_ptr<int> p3 = make_shared<int>();
//p4指向一个值为”999999999”的string
shared_ptr<string> p4 = make_shared<string>(,'');
//p5指向一个值初始化的int,即,值为0
shared_ptr<int> p5 = make_shared<int>();
auto p6 = make_share<vector<string>>();
1.3 share_ptr 的拷贝和赋值
当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象:
auto p = make_shared<int>(); //p指向的对象只有p一个引用者
auto q(p); //p和q指向相同对象,此对象有两个引用者
我们可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数(reference count)。无论何时我们拷贝一个shared_ptr,计数器都会递增;当我们给shared_ptr赋予一个新值或是shared_ptr被销毁时,计算器就会递减。
一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的对象:
auto r = make_shared<int>(); //r指向的int只有一个引用者
r = q; //给r赋值,令它指向另一个地址
//递增q指向的对象的引用计数
//递减r原来指向对象的引用计数
//r原来指向的对象已没有引用者,会自动释放
1.4 share_ptr 自动销毁所管理的对象
当指向一个对象最后一个 share_ptr 被销毁时,share_ptr 类会自动销毁此对象。它是通过另一个特殊的成员函数——析构函数完成销毁工作的。
2. shared_ptr 和 new 结合使用
我们可以使用 new 返回的指针来初始化智能指针,智能指针是一个类,分装了一个原始的 C++ 指针,用以管理所指对象的生命期。
shared_ptr<double> p1; //shared_ptr可以指向一个double
shared_ptr<int> p2(new int ()); //p2指向一个值为42的int
接受指针参数的智能指针构造函数是explicit的。因此,我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式来初始化一个智能指针:
shared_ptr<int> p1 = new int(); //错误:必须使用直接初始化形式
shared_ptr<int> p2(new int ()); //正确:使用了直接初始化
出于相同的原因,一个返回shared_ptr的函数不能在其返回语句中隐式转换一个普通指针:
shared_ptr<int> clone(int p){
return new int(p); //错误:隐式转换为shared_ptr<int>
}
shared_ptr<int> clone(int p){
return shared_ptr<int>(new int(p)); //正确:显式地用int*创建shared_ptr<int>
}
默认情况下,一个用来初始化智能指针的普通指针必须指向动态内存,因为智能指针默认使用delete释放它所关联的对象。我们可以将智能指针绑定到一个指向其他类型的资源的指针上,但是为了这样做,我们必须自己提供操作来代替 delete 。

c++基础(六)——动态内存的更多相关文章
- C和C指针小记(十六)-动态内存分配
动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...
- C++基础之动态内存
C++支持动态分配对象,它的生命周期与它们在哪里创建无关,只有当显示的被释放时,这些对象才会被销毁.分配在静态或栈内存中的对象由编译器自动创建和销毁. new在动态内存中为对象分配空间并返回一个指向该 ...
- 数据结构基础(1)--数组C语言实现--动态内存分配
数据结构基础(1)--数组C语言实现--动态内存分配 基本思想:数组是最常用的数据结构,在内存中连续存储,可以静态初始化(int a[2]={1,2}),可以动态初始化 malloc(). 难点就是数 ...
- 必须要注意的 C++ 动态内存资源管理(六)——vector的简单实现
必须要注意的 C++ 动态内存资源管理(六)——vector的简单实现 十六.myVector分析 我们知道,vector类将其元素存放在连续的内存中.为了获得可接受的性能,vetor ...
- 数据结构基础——指针及动态内存分配(malloc)
一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...
- C/C++基础----动态内存
why 管理较难,忘记释放会内存泄漏,提早释放可能非法引用,重复释放. 为了更容易,更安全的使用动态内存,提供智能指针,其默认初始化保存一个空指针. what shared_ptr允许多个指针指向同一 ...
- C语言之动态内存管理
C语言之动态内存管理 大纲: 储存器原理 为什么存在动态内存的开辟 malloc() free() calloc() realloc() 常见错误 例题 柔性数组 零(上).存储器原理 之前我们提到了 ...
- C++——类和动态内存分配
一.动态内存和类 1.静态类成员 (1)静态类成员的特点 无论创建多少对象,程序都只创建一个静态类变量副本.也就是说,类的所有对象都共享同一个静态成员. (2)初始化静态成员变量 1)不能在类声明中初 ...
- 转: Linux C 动态内存分配 malloc及相关内容 .
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
随机推荐
- LeetCode 947. Most Stones Removed with Same Row or Column
原题链接在这里:https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/ 题目: On a 2D plane ...
- 洛谷 P3469 [POI2008]BLO-Blockade 题解
一道经典的割点例题,用size数组记录该子树有多少个节点,sum是这棵搜索树上有多少个节点,sum*(n-sum-1)是将点删掉后的数对数量. #include<iostream> #in ...
- HTTP协议(待写)
先来了解了解 TCP/IP TCP/IP(Transmission Control Protocol / Internet Protocol)是计算机通讯必须遵守的规则,是不同的通信协议的大集合,其里 ...
- 如何抓取微信小程序的源码?
一.引言: 在工作中我们会想把别人的代码直接拿过来进行参考,当然这个更多的是前端代码的进行获取. 那么微信小程序的代码怎么样获取呢? 参考 https://blog.csdn.net/qq_4113 ...
- hibernate之一对多关系
1. 什么是关联(association) 1.1 关联指的是类之间的引用关系.如果类A与类B关联,那么被引用的类B将被定义为类A的属性.例如: public class A{ private B b ...
- Lightning Web Components 来自salesforce 的web 组件化解决方案
Lightning Web Components 是一个轻量,快速,企业级别的web 组件化解决方案,官方网站也提供了很全的文档 对于我们学习使用还是很方便的,同时我们也可以方便的学习了解salesf ...
- edgedb-js 来自官方的js 驱动
目前对于edgedb 主要还是来自官方的python驱动,目前js 版本的已经快发布了,代码在github 可以看到了 同时官方文档也提供了一个关于edgedb 内部的协议说明,结合js 驱动以及文档 ...
- 开发框架Express
一.使用原因 由于nodejs原生的http核心模块在某些方面不足以应对开发需求,所以就需要使用框架来加快开发效率,让代码更高度统一.在nodejs中有许多web开发框架,以下介绍Express的使用 ...
- mysql 字符类以及重复元字符
字符类 [:alnum:]=[a-zA-Z0-] [:alpha:]=[a-zA-Z] [:digit:]=[-] [:lower:]=[a-z] [:upper:]=[A-Z] [:xdigit:] ...
- Spring Cloud Gateway(十一):全局过滤器GlobalFilter
本文基于 spring cloud gateway 2.0.1 1.简介 GlobalGilter 全局过滤器接口与 GatewayFilter 网关过滤器接口具有相同的方法定义.全局过滤器是一系列特 ...