图文并茂C++精华总结 复习和进阶
字面常量不可以有引用,因为这也不需要使用符号来引用了,但是字面常量却可以初始化const引用,这将生成一个只读变量;
对变量的const修饰的引用是只读属性的;
也就是说,const修饰的引用,不管是变量初始化还是字面常量初始化,总是对应一个只读变量。
#
函数能够重载和返回值无关,所以两个函数若是只有返回值不同,这是无法重载的。
#
直接调用构造函数将产生一个临时对象,其生命周期只在一条语句时间,作用域仅在一条语句内。 现代C++编译器会尽量(是看情况去尽量,有些情况不一定确保)减少临时对象的产生,例如用一个临时对象来初始化一个新对象的场景。
减少临时对象产生,也就能减少构造函数调用的次数,加大程序执行的效率。
#
类中的const成员一定不是常量。 const成员函数注意事项:const成员函数在类中的声明处,和const成员函数的定义处,的后面,
加上const修饰。 const对象只能调用const成员函数,const成员函数只能调用const成员函数,
const成员函数内不可以直接改写成员变量的值。
注意理解上面的话,也就是说,
如果const对象的某个const成员函数内嵌套调用多个子成员函数,
那这些子成员函数都必须是const修饰。 const对象,可以定义非const与const成员函数,但是只能调用const成员函数。 const对象的成员变量是只读变量,编译时作是否在赋值符号左边的检查。
const对象的成员变量可以在构造函数(例如普通有参或无参构造函数和拷贝构造函数)中被初始化。要注意初始化和赋值的不同。
言不及意,具体请看下面图片代码所要表达之内容。
#
运算符重载规则和函数重载一样:根据函数参数决定能否构成重载关系,与返回值无关。
#
int a = 1; int b = ++a; 这样应该是a是2 b是2 。int a = 1; int b = a++; 这样应该是a是2 b是1 。
#
引用很容易与指针混淆,它们之间有三个主要的不同: 1 不存在空引用。引用必须连接到一块合法的内存。
2 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
3 引用必须在创建时被初始化。指针可以在任何时间被初始化。
#
静态成员变量在类外分配空间,是在全局数据区分配空间,也就是说其存储区和静态局部变量,全局变量是一样的。
同时需要注意,静态成员变量也必须在类的外部进行定义。
可以通过类名访问静态公有成员变量。静态成员变量为整个类所整个类所有。
和成员函数跟类似啊,那么,可以通过类名访问公有的成员函数吗?
==》 当然不可以,见下图
自己也假设个场景思考下该问题:
通过类名访问成员函数,不带this指针。
举个例子:假设通过类名了调用了一个该成员函数,且该成员函数内访问了某成员变量,
因此种方式调用成员函数不带有this指针,故无法判定该去获取哪个对象的成员变量)。
可以通过类名访问公有静态成员函数。但
是静态成员函数不可以直接访问非静态的成员变量,因为不含this指针信息。 静态成员函数不需要实例化就可以被调用,不可以调用非静态成员(包括静态成员变量和成员函数)
反正一个意思: 不带this指针的,和带this指针的,不能沾上边就行了。 因为非静态成员函数可以访问非静态的成员变量(每个对象都有自己各自的非静态成员变量),
这即表明非静态成员函数隐含了this指针信息, 而静态成员函数不含有this指针信息,这是固定属性,
也无法通过访问非静态成员来改变其属性,使其包含this指针信息。
关于静态成员函数与非静态成员函数。
我有点理解了,编译器就是搞了这两套东西。
相辅相成,为方便用户使用而做的。
条条大路通罗马,多搞他一条路,用起来时或许能方便些。 一套带this,一套不带this。前者是私家车,后者是公交车。
私家车上会有吃私房菜(调用非静态成员变量)的需要,所以要携带this指针信息。 公交车上就吃统一的盒饭:只能调用静态成员变量或其他静态成员函数
(如果调用了其他公交车,也肯是只能吃统一的盒饭)
对静态成员函数的一点备注,结合单例模式时的使用:
plus say: 上述截图扯到了单例模式,图中代码所展示的单例模式的使用方法也可以称之为二阶构造法。
二阶构造,应该说是个人的一种编程风格吧。第一阶段不涉及系统资源的申请,
那也可以合并入第二阶段啊。
本质还是要检查系统资源申请是否有效(大多是根据返回值检查,如new malloc fopen 等),
如果申请失败则执行析构函数,释放目前已经申请到的资源,
例如之前申请资源时,执行fopen文件a成功了,但是fopen文件b失败了,
所以在此处析构内应该执行fclose文件a)。
看来还要维护一个已打开资源的数组或链表。
二阶构造方法可以结合保存已打开资源的数组或链表,使得代码更加清晰,
一眼就能判断出析构的时机,以及在析构函数内应该释放哪些资源。
#
重载赋值操作符相对其他运算符有些特殊,只能作为成员函数来重载。
运算符重载规则和函数重载一样:根据函数参数决定能否构成重载关系,与返回值无关。
C++中的重载能够扩展操作符的功能。操作符的重载以函数的方式进行,操作符重载的本质就是用特殊形式的函数扩展操作符的功能。
我们使用operator关键字来标识该特殊函数。
#
引用是指针常量,指针常量是指如 int* const p = 。。。;这样的指针,也就是说*p是可以改变的。 int *p = new int(5);
int &a =*p;
此时p指向一个无名的变量,该变量由*p表示,所以int &a =*p;
这个问题可以查找c++标准关于operator*的返回值类型的描述。 是左值,才可以初始化非const引用。
来自网友菜鸟大神的解释: 用专业术语说,表达式*p的值是个int类型的左值,所以可以初始化非const引用。而 int a,b;
表达式a+b的值是int类型的右值,所以不能初始化非const引用。 关于左值和右值,可以参考c++标准operator*的返回值类型的描述。
我的实测如下图:
#
类的成员函数可以访问该类的所有成员变量,无论是否public修饰。类的成员函数只有一套,是共用的。
#
1. 只要一个类不含有虚函数, 那么实例化对象时,可以不必实现该类内部的成员函数,只声明即可。 2. 只要一个类拥有虚函数,当定义实例化该类对象时,就必须实现其全部的虚函数定义,否则编译报错。
( 当一个子类继承于父类时,子类内的重写虚函数(与父类内的某个虚函数:同函数名、返回值、函数参数)也是虚函数:
在实例化该子类对象时,也必须实现子类内部存在的全部虚函数定义,否则编译报错。)
#
要严格区分,只有在构造的时候,()和=可以无差别使用,都表示初始化。
但是在进行纯粹赋值的时候,例如非构造函数的其他成员函数在调用时被赋值,obj.normal_func() = 99;
此时只能用=来表示该赋值,而不能使用() .
要注意判别当前过程是构造还是赋值。
#
函数调用操作符是可重载的,且只能重载为类的成员函数。
函数调用操作符可以有多个不同的重载函数。
重载函数调用操作符的意义在于取代函数指针
(我的理解:
以前是传递函数指针,现在只需要传递对象引用即可,通过引用获取函数对象)。
有了函数对象以后,当我们看到MyClass obj; obj(99); 这样的语句们时,千万不要觉得诧异,
为啥已经构造过了,后面又调用一次obj(99) ?
那么此时单看仅有的这两条语句,应该存在两种可能性:
1. obj(99) 等价于obj=99, 这是在赋值
2.obj(99) 这是在调用obj对象的仅带一个参数的函数调用操作符的重载函数,99是传入的参数。
#
只能通过成员函数来重载数组操作符,该重载函数能且仅能使用一个参数。
数组操作符重载能够使对象模拟数组的行为。
#
如果一个类看似是空的,
实则包含了编译器默认提供的无参构造函数、拷贝构造函数、重载赋值操作符函数、析构函数。
当用户提供了自定义构造函数(自定义拷贝构造函数也算),编译器不再提供默认的无参构造函数。
#
在进行深拷贝的时候必须重载赋值操作符;
赋值操作符重载函数和拷贝构造函数具有同等的重要意义;
string类,在一块数据空间上保存字符数据,借助一个成员变量保存当前字符串长度信息;C++开发时应该避免C中的惯用思想,
例如指针使用、
直接通过char* p指向的字符串给string类对象赋值
(这种操作是不会改变string类对象内部表示字符串长度信息的成员变量的!)等。
#
智能指针一句话概念释义: 智能指针类对象在其生命周期结束后会自动释放所指向且涉及到的相关所有堆内存。
智能指针三板斧:
1. 在仅带一个参数的构造函数内对智能指针类内部的它类指针赋值,使其指向外部的它类对象。
2. 使用成员函数的方式重载指针访问->操作符(返回值为智能指针内部的它类指针) 和
*操作符(返回值为智能指针内部的它类指针指向的它类对象)。
3.在析构函数内delete它类指针(这就可以触发它类对象的析构函数被执行)。
按照上述已有的分析,我们现在或许可以写出令一个智能指针a指向一个智能指针b,再令b指向c…指来指去很多次,最后才指向实际的用户对象,这样的代码,
稍加思考,这必将成为日后bug的一个来源。
良好的编程经验要求: 一块堆内存最多只能由一个指针来标识。
这是非常重要的一点,
接下来我们继续实现的拷贝构造函数和赋值操作符重载函数就受此影响:
我们要完成指针指向内存所有权的转移(复制后,再delete原有的指针),而不是单纯复制。
#
#
#
#
#
#
#
#-----------------------------------------------------------
多种初始化方式: int a(5) ;、 int a=5; 、 int a{5}; 、int a[]{1,2,3};、int a[] ={1,2,3};
可以看出使用大括号{}符号初始化数组元素,会依次调用构造函数。
使用大括号{}符号初始化的优势是可以避免隐式转换
(待增补实验:用类的对象,子类对象初始化父类对象,来进一步验证该结论)。 ?
避免隐式转换的好处在于有时能通过编译器报错来使程序员能更全面地掌控程序。
#
#-----------------------------------------------------------
序列式容器,其存储的都是 C++ 基本数据类型(诸如 int、double、float、string 等)或使用结构体自定义类型的元素。 关联式容器则大不一样,此类容器在存储元素值的同时,还会为各元素额外再配备一个值(又称为“键”,其本质也是一个 C++ 基础数据类型或自定义类型的元素),
它的功能是在使用关联式容器的过程中,如果已知目标元素的键的值,则直接通过该键就可以找到目标元素,而无需再通过遍历整个容器的方式。
也就是说,使用关联式容器存储的元素,都是一个一个的“键值对”( <key,value> ),这是和序列式容器最大的不同。
除此之外,序列式容器中存储的元素默认都是未经过排序的,而使用关联式容器存储的元素,默认会根据各元素的键值的大小做升序排序。 C++ STL 标准库提供了 4 种关联式容器,分别为 map、set、multimap、multiset。
.
图文并茂C++精华总结 复习和进阶的更多相关文章
- 网络1712--c语言嵌套循环作业总结
1.助教有话说 首先,每周一篇的博客作业是很有必要的:编程的过程不仅仅是会敲几行代码.能够通过PTA就大吉大利了,你更应该做到的是梳理代码思路,通过与他人代码思路的比对,取其精华,进而不断进阶,才能逐 ...
- 初涉树形dp
算是一个……复习以及进阶? 什么是树形dp 树形dp是一种奇妙的dp…… 它的一个重要拓展是和各种树形的数据结构结合,比如说在trie上.自动机上的dp. 而且有些时候还可以拓展到环加外向树.仙人掌上 ...
- 工厂模式的进阶复习(Factory)
工厂模式进阶复习 看了多遍的工厂模式,老是忘记不同模式有什么区别,本文重点说明一下工厂模式的三种方式(简单工厂模式,工厂方法模式,抽象工厂模式)的区别 1.简单工厂模式 简单工厂模式通过Factory ...
- python 基础部分重点复习整理--从意识那天开始进阶--已结
pythonic 风格编码 入门python好博客 进阶大纲 有趣的灵魂 老齐的教程 老齐还整理了很多精华 听说 fluent python + pro python 这两本书还不错! 元组三种遍历, ...
- mxgraph进阶(三)Web绘图——mxGraph项目实战(精华篇)
Web绘图--mxGraph项目实战(精华篇) 声明 本文部分内容所属论文现已发表,请慎重对待. 需求 由于小论文实验需求,需要实现根据用户日志提取出行为序列,然后根据行为序列生成有向图的形式 ...
- 【Python全栈-后端开发】Django进阶之Model操作复习
Django进阶之Model操作复习 一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - ...
- JavaScript进阶【三】JavaScript面向对象的基础知识复习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Python复习笔记(三)函数进阶
问题 1:在函数内部,针对参数使用 赋值语句,会不会影响调用函数时传递的 实参变量? —— 不会! 无论传递的参数是 可变 还是 不可变 只要 针对参数 使用 赋值语句,会在 函数内部 修改 局部变量 ...
- Python复习笔记(二)变量进阶
02. 可变和不可变类型 不可变类型,内存中的数据不允许被修改: 数字类型 int , bool , float , complex , long(2.x) 字符串 str 元组 tuple 可变类型 ...
随机推荐
- springboot文件上传(可单文件/可多文件)
获取文件内容,是从InputStream中获取,添加到指定位置的文件 如下所示 public static void getFile(InputStream is,File fileName) thr ...
- 【深入理解Java虚拟机】Java虚拟机运行时数据区
Java虚拟机运行时数据区 线程私有 程序计数器 1.当前线程所执行的字节码的行号指示器. 2.唯一不会发生OutOfMemoryError的区域 3.如果执行的是java方法,计数器值为虚拟机字节码 ...
- Codeforece E. Anton and Permutation
主席树算贡献l,r中交换位置,算出>=rank(h) 和 <=rank(h) a[l],a[r] 先不统计 a[l]比a[r]大的话交换后ans-1,a[l]比a[r]小的话交换后ans- ...
- python简介以及简单代码——python学习笔记(一)
学习来源:https://www.liaoxuefeng.com/wiki/1016959663602400 了解python 简单编写并实现python代码 命令行模式和python交互模式 了解p ...
- 求学生单科流水表中单科最近/最新的考试成绩表的新增可行性方案 使用Oracle提供的分析函数rank
在 https://www.cnblogs.com/xiandedanteng/p/12327809.html 一文中,提到了三种求学生单科最新成绩的SQL可行性方案,这里还有另一种实现,那就是利用分 ...
- 20190923-03Linux时间日期类 000 011
1.基本语法 date [OPTION]... [+FORMAT] 2.选项说明 表1-20 选项 功能 -d<时间字符串> 显示指定的“时间字符串”表示的时间,而非当前时间 -s< ...
- python 模块安装导入
一.定义 python模块就是一个.py文件,一个模块中可以有多个函数,在使用模块时,只需要import下,就可以使用模块中的函数功能.import模块的过程相当于把这个py文件中的所有内容都执行一遍 ...
- SpringBoot 消息国际化配置
一.目的 针对不同地区,设置不同的语言信息. SpringBoot国际化配置文件默认放在classpath:message.properties,如果自定义消息配置文件,需要application.p ...
- java中双亲委派机制(+总结)
类加载器 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段"加载"过程中,需要通过一个类的全限定名来获 ...
- python 小脚本/自动重复访问网站(快速提高网页访问量)
来到csdn也快两个月了,前前后后写了20篇博客,但才1800+的访问量,其中恐怕还有300多是我自己点的 有点桑心(┬_┬) 于是打算另辟蹊径,自己刷访问量代码如下,需要自取 import urll ...