C++primer(第五版)第十二章(动态内存)

news2024/9/20 15:07:09

C++中内存包含静态内存,栈内存,自由空间(堆).

静态内存用于保存局部的static(静态)对象,以及定义于任何函数以外的变量(全局变量).

栈内存用来保存定义在函数内的非static对象,由编译器自动创建和销毁.

程序可以用堆来存储动态分配的对象,同时也需要由我们来显式地销毁.

12.1动态内存与智能指针

C++中动态内存的管理是由new和delete来完成的,由new来为对象分配空间并返回指向该对象的指针.由delete来对指针指向的对象进行销毁.

int *i=new int(10);   //创建
cout<<*i<endl;        //使用
delete i;             //销毁
cout<<*i<endl;        //抛出异常

新的标准库提供了两种智能指针(shared_ptr,unique_ptr),智能指针可以自动释放内存!

另外标准库还定义了名为weak_ptr的伴随类,它指向shared_ptr所管理的对象.

以上三种类型都定义在头文件memory头文件中.

12.1.1 shared_ptr类

智能指针也是模板,需提供指针可以指向的类型.

shared_ptr<string> p1;        //p1是可以指向string的shared_ptr
shared_ptr<vector<int>> p2;   //p2是可以指向元素类型为int的vector的shared_ptr

 默认初始化的智能指针中保存空指针.

 最安全的分配和使用动态内存的方法是调用来自标准库的函数make_shared,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr.我们一般用auto来接收,因为写起来比较简单.

shared_ptr<int> p1=make_shared<int>(10);    //一个指向10的shared_ptr
auto p2=make_shared<vector<int>>();        //一个指向元素类型为int的空vector的shared_ptr

当shared_ptr被拷贝或是赋值时,会有一个关联的计数器(可以这么理解)来记录有多少个其他shared_ptr指向相同的对象.可以通过p.use_count()来获取查看有多少个,主要用于调试.

当我们拷贝shared_ptr时,计数器会加一.当我们给shared_ptr赋予新值或是销毁时(离开作用域),计数器会减一,当计数器为0是,shared_ptr会自动释放自己所管理的对象.

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

使用动态内存通常出于以下三种原因:

程序不知道自己需要多少对象.

程序不知道所需对象的准确类型.

程序需要在多个对象间共享数据.

12.1.2直接管理内存

可以使用new来分配const对象,并且必须进行初始化.分配的是const对象时,new返回的是指向const的指针.

如果我们的自由空间耗尽,那么new会失败,并且抛出异常.我们可以改变new的方式来阻止抛出异常:

int *p=new (nothrow) int;    //如果分配失败,那么p为空指针(nullptr)而不是抛出异常

通常情况下,编译器无法分辨指针的指向,因此在释放内存前最好是先判断一下要释放的指针是否为空指针. 

内置指针(非智能指针)管理的动态内存在被显式释放之前都会一直存在,因此我们需要记得去释放,否则是及其消耗内存的.

使用内置指针通常会犯以下三个错误(因此书中推荐使用智能指针):

忘记delete内存.

使用已被释放的对象.

同一块内存释放两次.

delete之后,指针变成空悬指针,如果需要保留指针,那么最好是在delete之后,将其赋值为nullptr(空指针).

12.1.3 shared_ptr和new结合使用

使用new来初始化智能指针必须使用直接初始化形式:

shared_ptr<int> p1(new int(10));    //正确,使用直接初始化形式
shared_ptr<int> p2=new int(10);    //错误,new返回的是int*而不是shared_ptr

可以使用new,但是还是推荐使用shared_ptr.

并且非常不推荐混用普通指针和智能指针.

12.1.4智能指针和异常

智能指针的异常通常出现在get函数身上,p.get()会返回p保存的指针,如果智能指针p释放的其对象,那么get函数返回的指针指向的对象也会消失,因此只有确定代码不会delete指针的情况下才能使用get,并且不要用get初始化另一个智能指针或是给智能指针赋值.

为了减少异常,我们需坚持以下几条基本规范:

 12.1.5 unique_ptr

使用上unique_ptr和shared_ptr差不多.

不同的是unique_ptr一个时刻只能有一个unique_ptr指向一个对象,并且初始化时必须采用直接初始化形式.unique_ptr不支持拷贝或赋值操作.

 12.1.6 weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象.

 创建weak_ptr时需要一个shared_ptr来初始化它.

来通过weak_ptr访问对象时需要先用w.lock()来检查一下指向的对象是否存在

12.2动态数组

虽然书中有介绍动态数组的这个章节,但是同时也说了更推荐使用标准库容器.因此不再多介绍,只提炼出几点需要注意的点.

使用动态数组需要牢记动态数组并不是数组类型.

delete释放动态数组需要在delete后加上方括号[].

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/725967.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【第四天学习】数组

数组批量数据处理 数组的定义 速度是一个相同类型的用同一个标识符封装到一起的基本数据类型&#xff0c;可以使用一个统一的速度名或者是索引来唯一确定速度中的每个元素&#xff0c;它的执行效率非常高。 数组中每一个变量称为数组的元素&#xff0c;数组能够容纳元素的数…

Centos7安装wordpress图文教程

宝塔面板安装WordPress有两种方法&#xff1a; 自己手动安装&#xff08;推荐&#xff09;宝塔后台一键部署跳转提示 推荐使用手动安装&#xff0c;因为一键部署的WordPress版本不是最新的&#xff0c;而且自己上传的文件比较放心。 第一步&#xff0c;上传WordPress安装包 …

提升UE5写实效果的项目设置

随着虚幻引擎5&#xff08;Unreal Engine 5&#xff0c;简称UE5&#xff09;的发布&#xff0c;游戏开发者和数字艺术家们迎来了一个全新的机会&#xff0c;可以在其强大的渲染引擎下创建更加逼真和令人惊叹的游戏和虚拟场景。然而&#xff0c;要实现出色的写实效果&#xff0c…

经典轻量级神经网络(2)MobileNetV2及其在Fashion-MNIST数据集上的应用

经典轻量级神经网络(2)MobileNet V2及其在Fashion-MNIST数据集上的应用 1 MobileNet V2的简述 MobileNet V2 创新性的提出了具有线性bottleneck 的Inverted 残差块。这种块特别适用于移动设备和嵌入式设备&#xff0c;因为它用到的张量都较小&#xff0c;因此减少了推断期间的…

Redis 入门指南

Redis 入门指南 目录 Redis 入门指南 Redis 基本概念 Redis 常用命令 字符串String操作命令&#xff1a; 哈希Hash操作命令&#xff1a; 列表list操作命令 集合set操作命令&#xff1a; 有序集合sorted set 操作命令 通用命令 在Java中操作 Redis 1.Jedis 2.Spring …

windows后台窗口启动jar包

启动命令 chcp 65001 //切换utf-8 echo off start javaw -jar test-1.0-SNAPSHOT.jar --spring.profiles.activeprod echo 启动成功&#xff0c;按任意键结束 pause exit查看后台进程命令 wmic process where caption"javaw.exe" get processid,caption,commandli…

手机里的视频怎么转换成MP4格式?简单的转换方法分享

MP4格式是一种广泛使用的视频格式&#xff0c;几乎所有设备和操作系统都支持MP4格式的视频播放。无论是使用 iPhone、iPad、安卓手机、电视等各种设备&#xff0c;都可以播放 MP4 格式的视频。这种广泛的兼容性使得 MP4 成为一种非常方便的视频格式&#xff0c;我们可以随时随地…

IDEA自动生成实体类

操作流程 第一次需要配置Generate POJOs.groovy 新建该文件 Generate POJOs.groovy import com.intellij.database.model.DasTable import com.intellij.database.model.ObjectKind import com.intellij.database.util.Case import com.intellij.database.util.DasUtil import…

嵌入式面试刷题(day1)

文章目录 前言一、由for( ; ;)引出的一系列问题二、sizeof和strlen的误区三、字符串转义字符带来的问题四、结构体概念模糊五、&#xff01;和~概念分不清六、switch case误区七、短路运算八、复合赋值运算符带来的问题九、什么是左值什么是右值十、struct和union总结 前言 最…

cuda sample-asyncAPI(01)

C:\ProgramData\NVIDIA Corporation\CUDA Samples\v11.0\0_Simple\asyncAPI 这个例子说明了CUDA事件在GPU计时和CPU与GPU重叠执行方面的应用。 事件被插入到CUDA的调用流中。 由于CUDA流调用是异步的&#xff0c;CPU可以在GPU执行时进行计算&#xff08;包括主机和设备之间的DM…

【前端系列】前端如何使用websocket发送消息

序言 今天来学习一下前端如何使用websocket发送消息 1 基础介绍 1.1 什么是WebSocket WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议&#xff0c;它可以让客户端和服务器之间进行实时的双向通信。与传统的 HTTP 请求不同&#xff0c;WebSocket 使用了一个长连接&…

Django实现简单的音乐播放器 1

使用django框架开发一个简单的音乐播放器。 效果&#xff1a; 目录 环境准备 安装django 创建项目 创建应用 注册应用 配置数据库 设置数据库配置 设置pymysql库引用 创建数据库 创建数据表 生成表迁移文件 执行表迁移 配置时区 配置语言 配置子应用路由 在pla…

外部中断实验(stm32)

目录 EXIT的相关代码exit.cexit.h LED的相关代码KEY的相关代码BEEP的相关代码main.cGPIO 跟中断线的映射关系图 说明&#xff1a;以下内容参考正点原子资料 EXIT的相关代码 exit.c void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitS…

el-dialog中,el-form中表单信息未收集齐全时禁用提交按钮,动态控制按钮是否禁用

需求 在el-dialog中放置了一个表单&#xff0c;打开el-dialog时&#xff0c;表单没有收集内容&#xff0c;各项为空&#xff0c;此时表单的提交按钮被禁用&#xff0c;只有每个表单项都收集到内容时&#xff0c;才会将提交按钮设置为可用 预期效果 解决方案 <el-button c…

多线程进阶学习(高并发、线程池、使用场景)

文章目录 1、线程基础知识1.1、线程和进程线程和进程的区别&#xff1f; 1.2、并行与并发并行与并发有什么区别&#xff1f; 1.3、线程的创建方式创建线程的方式有哪些&#xff1f;刚才你说过&#xff0c;使用runnable和callable都可以创建线程&#xff0c;它们有什么区别呢&am…

OpenCV读取一张8位无符号三通道图像并显示

#include <iostream> #include <opencv2/imgcodecs.hpp> #include <opencv2/opencv.hpp> #include

Kafka生产者概述

【Kafka】Kafka生产者概述 文章目录 【Kafka】Kafka生产者概述1. 生产者1.1 生产者消息发送流程1.1.1 发送原理1.1.2 生产者重要参数列表 1.2 异步发送 API1.2.1 普通异步发送1.2.2 带回调函数的异步发送 1. 生产者 1.1 生产者消息发送流程 1.1.1 发送原理 在消息发送过程中…

企业数字化转型成功的标准是什么?

​近几年来&#xff0c;数字化转型一直是企业管理者的热议话题&#xff0c;那么&#xff0c;到底该以什么标准来衡量转型成效&#xff0c;又如何向管理者交出一份满意的答卷呢&#xff1f; 为了确保转型效果与目标的一致性&#xff0c;在规划数字化转型之初&#xff0c;选择正…

JVM — JDK11垃圾回收器 ZGC

1. ZGC介绍 ZGC&#xff08;The Z Garbage Collector&#xff09;是 JDK 11 中推出的一款低延迟垃圾回收器&#xff0c;为实现以下几个目标而诞生的垃圾回收器&#xff0c;停顿时间不超过 10ms&#xff0c;停顿时间不会因堆变大而变长&#xff0c;支持 8MB~4TB 级别的堆&#…

【专题速递】MD-VQA、AB实验、音视频质量建设以及在手机上的应用

// 怎样才能更好地进行QoE优化&#xff1f;音视频技术在用户侧的挑战又是什么&#xff1f;7月29日LiveVideoStackCon上海站QoE与数据驱动专场&#xff0c;为您解答。 QoE与数据驱动 在音视频应用里&#xff0c;获得了大量的用户上报数据&#xff0c;包括但不限于音视频质量数…