02 内联 new delete

news/2025/2/22 13:04:21/文章来源:https://www.cnblogs.com/xueshi/p/18719262


内联
函数调用流程:
程序执行顺序转移到函数所存放的内存中某个地址,将函数的程序内容执行完后,再返回到调用函数前的地方。要达到这样的目的必须在转去前,保护现场并存储执行的地址,转回后先恢复现场,并按照原存储地址继续执行。因此,函数调用有一定的时间和空间方面的开销,影响其效率。特别是对于一些函数体不大,但又频繁的调用的函数来讲,解决其效率问题更重要。
内联目的:
目的:解决因反复调用函数在时间和空间上的开销,影响其效率。
本质:编译时函数体中的代码被替代到程序中(空间换时间)
编译选项:
就算没有inline,编译器都会尝试编译成内联。提高效率,空间换效率,但是会不会内联成功不会告知
● /Ob0 取消内联关键字生效
● /Ob1 有关键字或满足其他语法,且内联不保证生效
● /Ob2 不管什么时候都尝试内联。
内联注意:
1.类内定义的函数是内联函数,类外定义的函数是非内联函数(短函数可以 定义在类内,长函数可以定义在类外)。

2.可以为类外定义的函数指定 inline ,强行为内联函数。

3.在内联函数内不允许用循环语句和复杂语句。

4.内联的定义必须出现在内联函数第一次被调用之前。
this指针
由于名称粉碎机制的存在,成员函数在编译的时候,会编译成一个全局函数。那么编译器是如何知道这个成员数据在哪里呢?

机制:在函数传递参数的时候,隐含传递了一个本类型的指针,this指针(对象本身的地址)。
this指针属性:指向本对象,且不可修改的指针
inline char* CMyString::SetString(/* CMyString const this ,/char* pszNew)
//隐含传递了一个CMyString的指针,this指针(对象本身的地址)
this指针与其他指针不同的地方:
不能监视窗口查看其值,(this指针存在寄存器中)
this指针不能更改,且只能指向对象本身。
new 和 delete
本质:new 内部会使用 _nh_malloc( cb , 1 ) 申请空间,当对象为类时,成功申请后自动调用合适的构造函数。

new 对象数组[]
机制:new对象数组的时候,在 &指针地址-4byte处存了一个计数器。

delete 对象数组
机制:对象数组delete的时候通过st2指针找到类型CMYString,对其类型求sizeof。
然后找到起始位置 - 4byte 得到count 乘 sizeof单个对象的大小,定位到最后一个对象,- 4字节处开始调用析构。
然后调用free 释放内存,且按照new的前后顺序,倒序释放。因为对象1不能依赖对象2,所以必须从后面开始释放。
有几个对象就要调用几个析构、

释放顺序:且按照new的前后顺序,倒序释放,因为对象1不能依赖对象2,所以必须从后面开始释放。
当对象是类时:会先调用析构函数,然后内部会使用free释放空间

delete常见崩溃
情况1:delete 对象数组
delete[] 释放单个对象崩溃的原因:释放的时候,把单个对象当做数组,此时对象的地址没变,去-4byte找count,由于此时没有count,读取到的是上溢标志FDFDFDFD次数来释放,这个次数太大了。

情况2:delete[] 对象
delete[] 释放单个对象崩溃的原因:释放的时候,把单个对象当做数组,此时对象的地址没变 去-4byte找count, 由于此时没有count,读取到的是上溢标志FDFDFDFD次数来释放,这个次数太大了。
const
编译器先扫描:以为界限,前面的修饰前面部分,后面的修饰右边变量
inline char
CMyString::SetString(/* const CMyString const this ,/char* pszNew) const
//后面加const 编译器理解为:const CMyString const *this 。目标和指针都不能改
类中适合const的成员函数:
适合不更改this指针的成员函数:GetString() const、GetLength()const

附加:中缀转后缀
eg:a+b*c-d/e
国语解释:a与bc之积,与de之商求差。
转换为汇编:sub(add(a,mul(b,c)),div(d,e))
编程求:二叉树中序遍历


附录:

include

include "CMyString.h"

include <string.h>

using namespace std;

/**********************************************************************

  • 就算没有inline编译器都会尝试编译成内联。提高效率,空间换效率,但是会不会内联成功不会告知
  • DeBug环境下。内联失效/Ob0
  • /Ob0 取消内联关键字生效
  • /Ob1 有关键字或满足其他语法,且内联不保证生效
  • /Ob2 不管什么时候都尝试内联。

*属性:

  • 类内的函数都默认内联。
    **********************************************************************/
    inline int MyMax(int x, int y)
    {
    return x > y ? x : y;
    }

//运行时常量 ,编译时常量
int const n = 666;

int main()
{

int* p3 = (int*) & n;
//*p3 = 999;  //ERROR:编译不通过,引发了异常: 写入访问权限冲突。cout << n << endl;  //输出还是666 的原因:常量传播。编译的时候,编译器扫描。发现n是常量,直接替换成n参加编译。CMyString str;
//指针会破坏类的封装性int* p = (int*)&str;   //说明不能访问是语法层面的限制:编译器限制
cout << *p << *(p + 1) << endl;//?SetString@CMyString@@QAEPADPAD@Z (&str,"Hello world");//后台调用。
str.SetString((char*)"world");

/*********************************************************************

  • new 和delete 属于运算符,可以通过运算符重载自定义其行为。
  • new 内部会使用 _nh_malloc( cb , 1 ) 申请空间,成功申请后自动调用合适的构造函数。
  • delete 会先调用析构函数,然后内部会使用free释放空间。
    *********************************************************************/
    int
    pn = new int;

/**********************************************************************

  • 情况①:delete 单个对象

**********************************************************************/
CMyString
st1 = new CMyString((char*)"Hello");
delete st1; //由代理函数调用析构函数,在调用free,debug版本下是free_dbg

/**********************************************************************

  • 情况②:delete[] 对象数组
  • 在delete对象数组的时候,编译器是如何知道new了几个对象呢?
  • 机制:delete 单个对象和对象数组的方式不一样。
  • 其根本在于,new对象数组的时候,在 &指针地址 -4beyt处存了一个计数器。
  • delete[] 对象数组d的时候通过st2指针找到类型CMYString,对其类型求sizeof。
  •        然后找到起始位置 - 4byte 得到count 乘 sizeof单个对象的大小,定位到最后一个对象,- 4字节处开始调用析构。
    
  •        然后调用free 释放内存,且按照new的前后顺序,倒序释放。因为对象1不能依赖对象2,所以必须从后面开始释放。
    
  •        有几个对象就要调用几个析构、 
    
  • delete释放对象数组造成崩溃的原因:吧count后面的字节当做堆数据区,此时不是堆数据的地址。
    (解析堆的信息出错)解析堆的时候附加数据读取乱套。
  • delete[] 释放单个对象崩溃的原因:释放的时候,把单个对象当做数组,此时对象的地址没变 去-4byte找count,
  •         由于此时没有count,读取到的是上溢标志FDFDFDFD次数来释放,这个次数太大了。
    

**********************************************************************/
CMyString
st2 = new CMyString[5];
delete[] st2;

/**********************************************************************

  • const
  • 编译器先扫描:以为界限,前面的修饰前面部分,*后面的修饰右边变量
    **********************************************************************/
return 0;

}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

08_基本数据类型介绍(测试发布文章)

08_基本数据类型介绍输入(问题):基本数据类型介绍?正例:输出(答案):知识描述:Java 数据类型分为两大类:基本数据类型(primitive data type)和引用数据类型(reference data type)。注意事项:引用数据类型的大小统一为 4 个字节,记录的是其引用对象的地址! 本章…

【CodeForces训练记录】Codeforces Round 1005 (Div. 2)

训练情况赛后反思 D题应该可以开出来的,看出了异或的性质,不等式可以移项,感觉是后缀异或+二分 A题 自己手玩一下就发现了,遇到首位1需要全部后缀移动到下面,再把首位0移动到上面,这样重复,所以我们从第一次出现 1 开始记录答案,操作次数为 01 交界处数量 + 1,另外特判…

DeepSeek-R1-671B 大模型本地部署详细教程

DeepSeek-R1大模型具备深度思考和推理能力,在数学、代码、自然语言推理等任务上都有着极大的提升。一方面由于官方或第三方的在线服务或多或少存在不稳定的问题,另一方面考虑到数据安全和隐私问题,本地私有化部署DeepSeek开源大模型对个人或企业来说也是一种不错的选择。本文…

引爆知识革命!Easysearch 携手 DeepSeek 打造下一代智能问答系统

去年我们尝试过使用 Easysearch + 千问 2 大模型打造一个企业内部知识问答系统,今年又有更加给力的大模型出现了--DeepSeek,性能对标 OpenAI o1 正式版。而且 Easysearch 对比去年也有了不少进步,是时候让我们升级下问答系统了。 DeepSeek 2025 年 1 月 20 日,人工智能领域…

人体碘元素知识

碘(化学符号:I,原子序数:53),碘是一种深紫色的固体,在常温常压下呈片状晶体。它具有较强的挥发性,当受热时,固体碘会直接转变为紫色的气体.在水中,碘不溶解,但可以溶解于一些有机溶剂中,例如乙醇和二甲苯。碘具有氧化性,在一些反应中可以作为氧化剂,例如氧化亚硫酸…

2025-02-16-snipd-format-for-obsidian

[!NOTE] This is a very early version, if something help, I would maintain it.Repo Meta<center>via: <a href=https://www.youtube.com/watch?v=bB-VWtidB5E target=_blank class=external-link>https://www.youtube.com/watch?v=bB-VWtidB5E</a><…

ingress生产环境安装方法

[!NOTE] 下载的Nginx Controller helm chart版本必须跟当前k8s版本兼容 官方参考地址:https://github.com/kubernetes/ingress-nginx/Supported Versions tableSupported Ingress-NGINX version k8s supported version Alpine Version Nginx Version Helm Chart Version🔄 v…

JUC并发-4.wait和notify以及Atomic原理

大纲 1.wait()与notify()实现一个简易的内存队列 2.wait()与notify()的底层原理 3.分布式存储系统NameNode机制介绍 4.分布式存储系统的edits log机制介绍 5.分布式存储系统的NameNode实现 6.分布式存储系统的创建目录功能的实现 7.edits log的全局txid机制和双缓冲机制实现 8.…

ACM寒假集训第六次专题任务

ACM寒假集训第六次专题任务 一、最大子段和 题目:解题思路: 维护两个变量:b 表示以当前元素结尾的最大子数组和,ans 表示全局的最大子数组和。遍历数组时,对于每个元素,更新 b 为当前元素值或当前元素与前一个最大子数组和的和(取较大值),同时更新 ans 为全局最大值。…

LGP9607 [CERC 2019] Be Geeks! 学习笔记

LGP9607 [CERC 2019] Be Geeks! 学习笔记 Luogu Link 题意简述 给定一个长为 \(n\) 的序列 \(A\)。 定义 \(G(l,r)=\gcd(a_l,a_{l+1}\cdots a_r)\); 定义 \(M(l,r)=\max(a_l,a_{l+1}\cdots a_r)\); 定义 \(P(l,r)=G(l,r)\times M(l,r)\); 计算 \(\sum P(i,j)[1\le i\le j\le…

卷积,toeplitz矩阵与傅里叶变换FT

卷积,toeplitz矩阵与傅里叶变换FT相关与卷积 一维相关和卷积运算是两个向量共同作用得到一个新的向量。 相关的分量形式: \[\begin{aligned} 映射(f: \mathbb{Z} \to \mathbb{R}),对于(w = (w(-a), \ldots, w(0), \ldots, w(a))), \\ 一维相关: g(x) = \sum_{s = -a}^{a}…

记录一次修复 JetBrains Rider 控制台输出乱码

在使用 JetBrains Rider 调试程序时,控制台输出日志出现了乱码。歪打正着结果困扰许久的问题得到了解决,于是记录下了这个小短文。 具体的修复建议如下:将终端编码设置为 GB2312 具体操作:设置->编辑器->常规->控制台->设置为 GB2312 ->保存之前在网上找各…