| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C++ Primer Plus 学习笔记(九) -> 正文阅读 |
|
[C++知识库]C++ Primer Plus 学习笔记(九) |
第12章 类和动态内存分配1. 动态内存和类当类中有静态成员,则所有该类对象共享一个该类成员
若创建了10个StringBad对象,则有10个 str 和 len,只有一个 num_strings。有一个对象更改该静态变量,所有其他对象的该变量都会改变。不能在类声明时初始化静态变量,这是因为会在类声明时分配内存,不过C++11可以类内初始化了... 静态成员一般在类方法文件中初始化:
在没有显示定义一些方法时, c++ 会自动生成一些成员函数,包括:默认构造函数,默认析构函数,复制(拷贝)构造函数,赋值运算符重载,地址运算符重载。隐式的地址运算符返回调用的对象的地址(即this指针)。c++ 11 有额外提供了移动构造函数和移动赋值运算两个方法。 默认构造函数的定义没有任何操作
它跟声明一个未初始化的变量的行为是一样的,该类对象成员的值在这种情况下时是未知的。 而一旦在类声明中显示声明了带参数的构造函数,则c++ 不会再生成默认构造函数,如需要默认构造函数,需要自己定义。带参数的构造函数,可以通过默认参数的形式,定义一个默认构造函数,但是它与不带参数的默认构造函数冲突,只能有一个。
复制构造函数的参数是类对象,用于初始化类对象,而不是类对象间赋值。
中间两种声明可能会直接调用复制构造函数初始化mtto和also,也可能通过复制构造函数像创建临时对象,然后通过赋值运算符重载赋值。最后一种,会初始化一个匿名对象,然后将该对象的地址赋值给pstring指针。 默认的复制构造函数会逐个复制非静态成员的值。生成临时对象时,也会调用复制构造函数,对于类构造函数中使用 new 的情况下,需要显示定义一个复制构造函数,来避免因创建类临时对象产生的内存泄漏问题,显示定义的复制构造函数也就是深度复制。
当没显示定义复制构造函数时,当创建一个类对象的临时对象时(如按值将类对象作为函数参数),临时对象出作用域时会自动调用析构函数,这样原对象的 str 指针和临时对象的 str 指针指向相同的 new 地址,指向的 new 地址就会泄漏。复制构造函数不仅复制数据地址,也要复制数据。
默认的赋值运算符重载同默认复制构造函数类似,逐值赋值非静态类成员,同样对于类构造函数中使用 new 的情况下,需要显示定义赋值运算符的重载,来防止 new 的内存泄漏。
析构函数中 delete 的形式要和构造函数中 new 的形式对应,即 new int [],则 delete [];new int, 则 delete 。
delet 或者 delete [] 都可以作用于空指针,因此上面的定义等价于:
可以将类成员函数声明为静态的(声明时必须包含关键字 static,如果是单独定义的,则定义时不能包含 static),不能通过类对象调用静态成员函数,实际上,静态成员函数不能使用 this 指针。若静态成员函数是公有的,可以通过类名和作用域解析符来调用它。静态成员函数只能只能使用类的静态成员,即 StringBad 类对象的静态成员函数只能使用 num_strings,而不能使用 str 和 len。
2. 使用指向对象的指针使用指向类对象的指针,如:
将调用复制构造函数初始化一个未命名的类对象,pt 指向这个对象的地址
将调用默认构造函数。 在使用指向对象的指针时,new 分配的内存负责储存 str 和 len的值,str 指向的字符串由构造函数分配内存,当类对象出作用域时,调用析构函数会 delete str 指向的字符串内存,因此还需要? delet pt;来释放类对象的内存(不带 [] ),当对象是通过 new 创建的,只有当显式调用 delete pt 时,才会调用该对象的析构函数。调用类方法时,使用 “ ->" 运算符代替 " . "。 当使用定位 new 运算符时创建对象时,会产生覆盖的情况,在构造函数有 new 的情况会产生问题:
当 delete [] buf 时,也不会为定位 new 运算符创建的对象调用析构函数。因此,在使用定位 new 运算符连续创建对象时,要提供不同的存储位置:
在使用 定位 new 运算符创建对象时,无法这样释放对象:delete pc2;这是因为pc2并没有收到 new 返回的地址,而当 delete pc1;时,也只会释放 buf 指向的那块512字节的内存块,这是因为pc1 与 buf 的地址相同。因此,对于定位 new 运算符创建对象的情况,要显示的调用析构函数来释放对象:
3. 队列模拟在类中嵌套结构或类声明,声明的作用域是整个类,不会与其他类或者全局等同名声明冲突:
如果 Node 声明在公有部分,可以在类的外部,通过作用域解析运算符使用这个声明的类型:Queue::Node node;。 当 Queue 类的公有方法为私有的变量赋值时,qsize 会出现问题,它是 const 修饰的常量,常量只能初始化,而无法先声明再赋值。在调用构造函数时,如有一个构造函数 Queue(int qs) { qsize = qs;},对象将在代码执行前就被创建,这时候在为 qsize 赋值就会报错了。C++ 采用成员初始化列表解决这个问题:
这种方法不局限于初始化常量:
只有构造函数可以使用成员初始化列表的方式,类中有 const 成员或者引用成员的时候,必须使用这种方法,引用也只能初始化,无法先声明后赋值。 C++ 11 开始允许在类内初始化变量:
这与在构造函数中使用成员初始化列表等价。 数据成员被初始化的顺序与它们在类内声明的顺序相同,与初始化器的排列顺序无关。 ? ? |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 16:38:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |