16.1 C++智能指针-new/delete探秘

2023-11-20

16.1 C++智能指针-new/delete探秘
16.2 C++智能指针-shared_ptr
16.3 C++智能指针-weak_ptr
16.4 C++智能指针-shared_ptr使用场景、陷阱、性能分析与使用建议
16.5 C++智能指针-unique_ptr

    智能指针的引入正是为了防止无意之间写出有内存泄漏的程序。内存释放的工作将交给智能指针来完成,在很大程度上能够避免程序代码中的内存泄漏。

1.new/delete探秘

  • new/delete是什么
        new/delete和malloc/free最明显的区别之一就是使用new生成一个类对象时系统会调用该类的构造函数,使用delete删除一个类对象时系统会调用该类的析构函数(释放函数)。既然有调用构造函数和析构函数的能力,这就意味着new和delete具备针对堆所分配的内存进行初始化(把初始化代码放在类的构造函数中)和释放(把释放相关的代码放在类的析构函数中)的能力,而这些能力是malloc和free所不具备的。
  • operator new()和operator delete()
        new运算符做了两件事:①分配内存;②调用构造函数初始化该内存。
        delete运算符也做了两件事:①调用析构函数;②释放内存。
  • new如何记录分配的内存大小供delete使用
        不同编译器的new内部都有不同的实现方式
  • 申请和释放一个数组
        为数组动态分配内存时,往往需要用到[],如new[…],而释放数组时,往往也要用到[],如delete[…],这意味着,往往new[]和delete[]要配套使用。
  • 为什么new/delete、new[]/delete[]要配对使用
        如果一个对象,是用new[]分配内存,而却用delete(而不是delete[])来释放内存,那么这个对象满足的条件是:对象的类型是内置类型(如int类型)或者是无自定义析构函数的类类型。
A * pA = new A[2];    //这里不再分配6字节,而是2字节
delete pA;            //这里不再出现内存泄漏,也不再报异常

    那事情反过来看,如果类A书写了自己的析构函数,则用new[]为对象数组分配内存,而用单独的delete来释放内存,就会报异常。

A * pA = new A[2];    //这里分配6字节
delete pA;            //这里报异常 为什么异常?

    报异常的原因是,代码行“delete pA;”做了两件事:
    (1)调用一次类A的析构函数。new的时候创建的是两个对象,调用的是两次构造函数,而释放的时候调用的是一次析构函数,虽然不致命,但也存在后遗症(如类A的构造函数中如果分配了内存,指望在析构函数中释放内存,那么如果少执行一次析构函数,就会直接导致内存的泄漏)
    (2)调用“operator delete(pA);”来释放内存。系统所报的异常,其实就是执行这行代码的调用导致的。就是因为多分配这4字节的问题导致释放的内存空间错乱。例如,明明应该释放一个0x00000012作为开始地址的内存,因为内存空间错乱,导致释放了0x00000016作为开始地址的内存,从而导致出现异常。
    所以,new/delete、new []/delete[]要配对使用,否则程序运行出错。

#include <iostream>
#include <vector>
using namespace std;   //后面再使用诸如std::cout时就可以简写成cout了;
class A
{
public:
    A()
    {
        cout << "A" << endl;
    }
    int m_i;
};
int main()
{
    {
        int* pointi = new int; //pointi指向一个int对象
        string* mystr = new string;                
    }
    {
        int* pointi = new int(100); //跟踪调试,指针指向的值变成了100
        string* mystr2 = new string(5, 'a'); //生成5个a的字符串,调用的是符合给进去的参数的string构造函数来构造出合适的字符串内容
        vector<int>* pointv = new vector<int>{ 1,2,3,4,5 }; //一个容器对象,里面有5个元素,分别是1,2,3,4,5
    }
    {
        string* mystr2 = new string(); //“值初始化”,感觉和string *mystr = new string;效果一样,总之最终字符串内容为空("")
        int* pointi3 = new int(); //值被初始化为0, 这个()加与不加确实不一样,只有加了()值才会被初始化为0    
    }
    {
        A* pa1 = new A;
        A* pa2 = new A();
    }
    {
        string* mystr2 = new string(5, 'a');
        const char* p = mystr2->c_str();
        auto mystr3 = new auto(mystr2); //注意这种写法,mystr3会被推断成string *类型
        //string** mystr3 = new (string *)(mystr2);        
        delete mystr2;
        delete mystr3;                
    }
    {
        const int* pointci = new const int(200); //new后面这个const可以不写,似乎都差不多;当然const对象不能修改其值
        //*pointci = 300;  //不合法        
        cout << "断点放到这里方便观察" << endl;
        delete pointci; //new的内存不能忘记释放
    }
    {
        char* p = nullptr;
        delete p;
        delete p;
    }
    {
        int i;
        int* p = &i;
        //delete p; //不是new出来的不能delete,否则编译不报错,但执行时会出现异常
    }
    {
        int* p = new int();
        int* p2 = p;
        delete p2; //没问题
        //delete p; //异常,因为p和p2指向同一块内存,该内存已经通过delete p2释放了,所以两个指针指向同一块内存这种,也比较麻烦,释放了p就不能再释放p2,释放了p2就不能再释放p,换句话说,如果释放了p2,也就不能再使用p
    }
    {
        const int* pci = new const int(300);
        delete pci; //可以delete const对象
    }
    {
        int* pci = new  int(300);
        delete pci; //可以delete const对象
        *pci = 900;
    }
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

16.1 C++智能指针-new/delete探秘 的相关文章

  • 在java程序中使用c++ Dll

    我正在尝试使用System LoadLibrary 使用我用 C 编写的一个简单的 dll UseDllInJava java import com sun jna Library import com sun jna Native imp
  • 分段错误(核心转储)错误

    我的程序编译罚款 但在输入文件时出现 分段错误 核心转储 错误 我没有正确处理 ostream 吗 include
  • C 程序从连接到系统的 USB 设备读取数据

    我正在尝试从连接到系统 USB 端口的 USB 设备 例如随身碟 获取数据 在这里 我可以打开设备文件并读取一些随机原始数据 但我想获取像 minicom teraterm 这样的数据 请让我知道我可以使用哪些方法和库来成功完成此操作以及如
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • ASP.NET Core 与现有的 IoC 容器和环境?

    我想运行ASP NET 核心网络堆栈以及MVC在已托管现有应用程序的 Windows 服务环境中 以便为其提供前端 该应用程序使用 Autofac 来处理 DI 问题 这很好 因为它已经有一个扩展Microsoft Extensions D
  • SSL/TLS/HTTPS 站点在 C#/.NET WebBrowser 控件中非常慢,但在 Internet Explorer 中则很好

    背景 我正在修改自动维基浏览器 http en wikipedia org wiki Wikipedia AutoWikiBrowser使用托管在安全服务器上的 MediaWiki 站点 我允许用户通过 C 应用程序中的 WebBrowse
  • 将字符串中的“奇怪”字符转换为罗马字符

    我需要能够将用户输入仅转换为 a z 罗马字符 不区分大小写 所以 我感兴趣的角色只有26个 然而 用户可以输入他们想要的任何 形式 的字符 西班牙语 n 法语 e 和德语 u 都可以包含用户输入中的重音符号 这些重音符号会被程序删除 我已
  • 从 C 结构生成 C# 结构

    我有几十个 C 结构 我需要在 C 中使用它们 典型的 C 结构如下所示 typedef struct UM EVENT ULONG32 Id ULONG32 Orgin ULONG32 OperationType ULONG32 Size
  • 获取尚未实例化的类的函数句柄

    我对 C 相当陌生 我想做的事情可能看起来很复杂 首先 我想获取一些函数的句柄以便稍后执行它们 我知道我可以通过以下方式实现这一目标 List
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 对 boost 库的依赖项没有完整路径

    我已经成功构建了动态库 依赖于使用自定义前缀构建和安装的 boost 库 b2 install prefix PREFIX 然而 当我跑步时otool L在我的库中 我得到如下输出 libboost regex dylib compatib
  • libxml2 xmlChar * 到 std::wstring

    libxml2似乎将所有字符串存储在 UTF 8 中 如xmlChar xmlChar This is a basic byte in an UTF 8 encoded string It s unsigned allowing to pi
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 如何随着分辨率的变化自动调整大小和调整表单控件

    我注意到某些应用程序会更改控件的位置以尽可能适应当前的分辨率 例如 如果窗口最大化 则控件的设置方式应使整个 GUI 看起来平衡 是否可以使用 C 在 Visual studio 2010 中制作或实现此功能 Use Dock http m
  • DataTable:通过 LINQ 或 LAMBDA 进行动态 Group By 表达式

    我有一个数据表 我想在其中对未指定数量的字段进行分组 发生这种情况的原因是用户可以选择他想要分组的字段 所以 实际上 我将选择推入列表中 在这个选择上 我必须对我的数据表进行分组 想象一下这段代码 VB 或 C 都一样 public voi
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • 如何引用解决方案之外的项目?

    我有一个 Visual Studio C 解决方案 其中包含一些项目 其中一个项目需要引用另一个不属于解决方案的项目 一开始我引用了dll
  • C++、三元运算符、std::cout

    如何使用 C 用三元运算符编写以下条件 int condition1 condition2 condition3 int double result int or double std cout lt lt condition1 resul
  • 以 UTF8 而不是 UTF16 输出 DataTable XML

    我有一个 DataTable 我正在使用 WriteXML 创建一个 XML 文件 尽管我在以 UTF 16 编码导出它时遇到问题 并且似乎没有明显的方法来更改它 我了解 NET 在字符串内部使用 UTF 16 这是正确的吗 然后 我通过
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • PageAbility基本概念

    作者 韩茹 公司 程序咖 北京 科技有限公司 鸿蒙巴士专栏作家 一 Page与AbilitySlice Page Page模板 以下简称 Page 是FA唯一支持的模板 用于提供与用户交互的能力 一个Page可以由一个或多个AbilityS
  • QtWebassembly中文显示支持

    Qt Webassembly中文显示支持 由于webassembly是运行在wasm虚拟环境中的 因此是无法直接访问当前系统字体 如果需要提供中文或其它字体支持需要将字体文件作为资源与应用一起编译打包到wasm中 并在应用中主动加载字体资源
  • HTML5学习(三):布局标签、列表、超链接和id

    1 布局标签 header表示网页的头部 页眉 main表示网页的主体部分 一个页面中只会有一个main footer表示网页的底部 页脚 nav表示网页中的导航 aside和主体相关的其他内容 侧边栏 article表示一个独立的文章 s
  • Linux系统上Hadoop的配置

    目录 1 免密登录 2 设置java安装的根目录 3 hadoop参数配置 hadoop地址配置 1 免密登录 cd ssh ls ssh keygen t rsa P f ssh id rsa ls 多了两个文件 id rsa id rs
  • 杭电ACM 1004题

    原题大概意思就是统计输入字符串中 重复的最大个数 import java util Scanner public class Main public static void main String args Scanner sc new S
  • C++ Primer 第五版 电子书(英文)pdf下载

    C Primer 第五版 电子书 英文 pdf下载下载链接 https pan baidu com s 13BQ93O0g8QaNq4ultcxhKA 提取码获取方式 关注下面微信公众号 回复关键字 1169
  • Tensorflow 机器翻译NMT笔记 1 快速上手

    开始 首先 这篇博客基本基于 https github com tensorflow nmt 的内容来的 作为个人学习的笔记 也当做一个博客内容分享 顺序和Github上的顺序有一些区别 注意咯 首先 这里讲的是一个基于Seq2Seq实现的
  • Python 正则表达式指南

    文章目录 1 正则表达式基础 1 1 简单介绍 1 2 数量词的贪婪模式与非贪婪模式 1 3 反斜杠的困扰 1 4 匹配模式 2 re模块 2 1 开始使用re 2 2 Match 2 3 Pattern 1 正则表达式基础 1 1 简单介
  • Vue2基础框架(js)

    快捷方式 vba div div
  • IO相关-这一篇全了解

    什么是比特 什么是字节 什么是字符 它们长度是多少 各有什么区别 解 Bit最小的二进制单位 是计算机的操作部分 取值0或者1 Byte是计算机操作数据的最小单位由8位bit组成 取值 128 127 Char是用户的可读写的最小单位 在J
  • 由一个多线程共享Integer类变量问题引起的。。。

    假设并发环境下 业务代码中存在一些统计操作 为了保证线程安全 开发人员往往会对计数值进行加锁 synchronized 值得注意的是 直接对Integer类型进行加锁 似乎并不会达到预期效果 比如下面这段代码 Integer num new
  • java 视频压缩

    原文链接 https blog csdn net SeniorShen article details 113246990 1 引入依赖
  • C++拷贝构造函数的使用:创建类Dog 成员变量name age 。完成该类的定义,该类包含构造函数,拷贝构造函数 析构函数

    创建类Dog 成员变量name age 大家完成该类的定义 该类包含构造函数 拷贝构造函数 析构函数 拷贝构造函数的作用 拷贝构造函数作用就是利用该类的一个对象是初始化另一个该类的对象 换句话说就是 拷贝构造函数的作用 通过一个对象对该类的
  • 使用ADB命令来测试Android手机App的耗电量

    1 使用WiFi连接手机 先使用USB数据线连接手机和电脑 手机和电脑连接同一个WiFi 启动端口服务 adb tcpip 5555 5555为端口号 可以自由指定 打印 restarting in TCP mode port 5555 表
  • 如何用Stata完成(shui)一篇经济学论文(十一):分组和去重

    文章目录 分组 去重 不出意外的话 这应该是stata有关数据处理的最后一篇 emmm 其实我一开始只打算写数据处理部分的stata教程 因为我觉得对于我来说 数据处理才是最头疼的部分 不过关于后面回归 还是有些东西想跟大家分享一下 开始挖
  • Halcon直线检测

    1 Halcon最常用的直线检测算子 add metrology object line measure 利用Halcon封装好的模型不仅可以检测直线 还可以检测圆 椭圆 矩形等 下面介绍下其余的直线检测的算子 需要配合 skeleton
  • CentOS7安装postgresql

    目录 1 安装postgresql 2 postgresql基本使用 常用启停命令 常用配置文件 常用postgresql命令 官网地址 https www postgresql org 1 安装postgresql 1 1 进入官网 点击
  • 两点。。。等来金蝶中间件的面试通知

    晚上笔试 说是大约一点通知 等到十二点 困了 上床 睡不着啊 1点半翻起来 打开手机 没有 打开Gmail 没有 于是抽了支烟 等到两点多一点 手机响了 接到面试通知 下午一点 石头终于落地 因为上午还有一场网易游戏的笔试 担心冲突 还好
  • Linux编辑器——vim的使用

    文章目录 1 vim的三种模式 2 vim的基本操作 3 vim的配置 前言 Linux上的编辑器有很多 比如nano vi vim等 nano是最简单的编辑器 vim编辑器常用于写代码 因为vim的功能强大 写代码快捷方便 其可以主动的用
  • 16.1 C++智能指针-new/delete探秘

    16 1 C 智能指针 new delete探秘 16 2 C 智能指针 shared ptr 16 3 C 智能指针 weak ptr 16 4 C 智能指针 shared ptr使用场景 陷阱 性能分析与使用建议 16 5 C 智能指针