首页 > 系统相关 >[Primer] 第 12 章 类和动态内存分配

[Primer] 第 12 章 类和动态内存分配

时间:2023-03-07 22:23:00浏览次数:48  
标签:12 对象 运算符 重载 复制 动态内存 赋值 Primer 构造函数

第 12 章 类和动态内存分配

12.1 动态内存和类

通常最好在程序运行时,而不是编译时决定内存的分配。

不能在类声明中初始化静态变量,因为类声明仅仅提供了类的属性而没有分配内存,因此只能在类实现中初始化。将静态变量声明为 const 或转换为枚举类型则可以在声明中初始化。

如果没有声明,则类会自动生成部分成员函数,即默认构造函数、默认析构函数、复制构造函数、赋值运算符、地址运算符(返回 this 指针的值)、移动构造函数、移动赋值运算符。

复制构造函数用于将一个定义好的对象复制到新创建的对象中,其原型为 ClassName(const ClassName &);,新建一个对象并初始化为已有对象时会调用复制构造函数,Example e1(e2); Example e1 = e2; Example e1 = Example(e2); Example *e1 = new Example(e2); 都会调用复制构造函数。

按值传递意味着创建原始变量的一个副本,创建临时变量时(函数参数等)也会调用复制构造函数。

默认复制构造函数逐个复制非静态成员,如果成员本身是类对象,则会调用该类的复制构造函数来复制成员对象,成员复制也被称为浅复制。

浅复制存在隐含的问题,即如果类成员中有指针对象,则只会复制对象的地址而不会新构造一个对象再指向它,因此当复制对象指针指向内存被释放后,浅复制的对象中的指针将指向一个已经被释放的内存空间进而导致错误。解决这个问题的办法是进行深复制,显式地定义复制构造函数创建一个相同的对象,再创建新的指针指向新的对象。

如果一些类成员是使用 new 初始化的指向数据的指针,则必须定义复制构造函数。

将已有的对象赋给另一个对象时将使用重载的赋值运算符,类似 Example e1 = e2; 的初始化对象有可能先用复制构造函数创建一个临时对象,再用重载赋值运算符将临时变量赋给 e1,也有可能只调用复制构造函数。

重载赋值运算符与复制构造函数类似,逐个复制非静态成员,如果成员本身是类,则通过该类的赋值运算符复制成员。

赋值运算符的重载与复制构造函数的重载类似,都需要进行深复制。不同的地方在于重载赋值运算符需要先检查是否为自我复制,如果是则可以直接返回 *this,另外还需要释放已经申请的空间,因为赋值后会分配新的空间。

12.2 改进后的新 String

使用 nullptr 而不是 0 表示空指针。

有时需要提供仅供 const 对象使用的 const 函数,C++ 区分常量和非常量函数的特征标。

不能通过对象调用静态函数,需要通过类名和作用域解析运算符调用。静态函数只能使用静态成员。

12.3 在构造函数中使用 new 时应注意的事项

使用 new 初始化成员指针时应该在析构函数中使用 delete;如果有多个构造函数则必须使用同样的方式使用 new,都使用中括号或都不使用,因为析构函数只有一个,所有构造函数都需要和它兼容;自定义显式复制构造函数实现深复制;自定义显式重载赋值运算符检查自我赋值或释放内存并实现深复制。

12.4 有关返回对象的说明

返回对象将调用复制构造函数,而返回引用不会。引用指向的对象应该在调用函数执行时存在。

重载赋值运算符与和重载 cout 一起使用的 << 运算符一般返回指向非 const 对象的引用。

如果返回的是函数内的局部变量,则不应该返回对象的引用,因为函数执行完成后内部对象会调用析构函数,对象不再存在,它的引用自然也没有意义了。通常重载运算符需要返回对象而不是引用。

12.5 使用指向对象的指针

使用 new 创建对象时,首先为对象分配内存,再调用构造函数依次将参数复制到分配的内存单元中,然后创建对象变量,最后把分配内存的地址赋给变量。

delete 可以与常规的 new 运算符配合使用,但不能和定位 new 一起使用。这时销毁对象需要显式地调用析构函数,即 obj->~Object();,销毁一系列对象时应按照与创建顺序相反的顺序,因为新对象可能依赖旧对象,而且仅当所有定位 new 对象都被销毁后才可以销毁存储这些对象的缓存区。

12.6 复习各种技术

12.7 队列模拟

必须使用初始化列表初始化非静态 const 成员或引用成员,因为它们只能被初始化而不能被赋值。

定义私有复制构造函数和重载赋值运算符可以避免意外调用。

标签:12,对象,运算符,重载,复制,动态内存,赋值,Primer,构造函数
From: https://www.cnblogs.com/futureknight/p/17189946.html

相关文章

  • 每日小结(12)
    冒泡排序是一种基本的排序算法,它的原理是比较相邻的元素,如果顺序错误就交换它们。这样一轮比较下来,最大的元素就会移动到最后的位置。然后重复这个过程,直到所有元素都被排......
  • 每日总结12
    所用时间:下午两个小时代码:400博客:2知识点:实现打卡功能打卡完成页面打卡数据表打卡信息保存,更改,查询    ......
  • MySQL用户新建表报1227异常
    1、MySQL8新建用户createuser'firestone'@'%'identifiedby'123456';2、给用户授予test库所有权限grantallprivilegesonfirestone_pretank.*to'firestone'@'%';3......
  • 优化 CSS 代码的12个小技巧
    优化CSS代码的12个小技巧2022-11-2509:03·Echa攻城狮 大家好,我是Echa。今天来分享12个优化CSS代码小技巧!1.避免高消耗属性分析表明,一些CSS属性的渲染速......
  • 分享12款我常用的开源免费软件
    分享12款我常用的开源免费软件原创2023-02-1613:40·趣谈前端作者:徐小夕来源:趣谈前端公众号嗨,大家好,我是徐小夕,在一个劳动力追求高性价的时代,我们无时无......
  • 3.7每日总结12
    今天用了一个半小时的时间边学习边做后台数据注册的内容,其中学习了如何在后台获取前台按钮的结果,和如何获取前台文本输入框的结果和提示框。详细代码如下 ......
  • 12N60-ASEMI高压MOS管12N60
    编辑-Z12N60在TO-220封装里的静态漏极源导通电阻(RDS(ON))为0.7Ω,是一款N沟道高压MOS管。12N60的最大脉冲正向电流ISM为48A,零栅极电压漏极电流(IDSS)为1uA,其工作时耐温度范......
  • C++ primer 智能指针的陷阱
    1.不使用相同的内置指针值初始化(或reset)多个智能指针有一个现成的约定是当我们将一个原生指针交给(具有资源所有权的)智能指针的时候,这个智能指针被允许认为自己暂时获得......
  • 120. Triangle
    题目Givenatriangle,findtheminimumpathsumfromtoptobottom.Eachstepyoumaymovetoadjacentnumbersontherowbelow.Forexample,giventhe......
  • 《安富莱嵌入式周报》第305期:超级震撼数码管瀑布,使用OpenAI生成单片机游戏代码的可玩
    往期周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 说明:谢谢大家的关注,继续为大家盘点上周精彩内容。 视频版:h......