new与malloc?
int* pointer = new int(1);
Solution* s1 = new Solution(1);
int* b = (int*)malloc(sizeof(int)*10);
- 1.new和delete为C++关键字;malloc和free为C库函数。
- 2.new申请以类型为单位内存空间,触发构造函数,初始化内存。delete销毁对象,触发析构函数;malloc申请以字节为单位的内存,仅仅进行内存的申请,free释放,还得将指针赋空,否则出现野指针。
- 3.new返回值为指定类型的指针,创建失败返回异常;malloc返回值为void*,失败返回NULL;
指针和引用
int i = 0;
int* p = &i;
int& b = i;
- 1.指针是变量,值地址;引用是内存别名
- 2.指针可为空,引用不能为空
- 3.指针可多次绑定不同内存,引用只能取一次别名
- 3.指针对指向内存操作通过*p,而引用直接操作b
- 4.变异阶段引用的内部实现考的是常量指针的操作
C++的三大特征
继承、封装、多态
继承(展现类之间的关系,还有组合)
实现代码扩展,子类会继承父类,拥有父类的成员,因为继承的方式不同,封装了许多模块远
- (public(原来的访问权限)、private(全部变成私有成员)和protected(共有成员变成保护成员,只能子类访问))
- 符合现实的逻辑,如:人类、男人、教师、父亲
封装(实现代码模块化编程)
- 封装方式:public、private、protected
- public封装对象能访问所有成员
- private和protected封装只能在类内部访问
- protected封装子类可访问
- 如:女生的年龄不想让人知道,可封装为private
多态(程序运行过程中出现动态特性)
- 表现形式:联编(函数调用和执行该操作的代码的映射关系)
- 静态联编:程序编译阶段确定函数调用和操作代码之间的映射关系
- 动态联编:程序在执行时才能进行联编工作(C++中的动态联编在虚函数的支持下实现的)
静态联编
- 函数重载:同一作用域下相同函数名不同参数构成不同的独立函数
- 编译器如何选择重载函数:函数类型和参数列表
动态联编
- 在不同继承关系的类对象,去调同一函数,产生了不同的行为。
- 调用函数的对象必须是指针或者引用。
- 被调用的函数必须是虚函数,且完成了虚函数(virtual声明的函数)的重写(父子类间)。
虚函数
- virtual声明的函数叫虚函数
- 为了允许用基类的指针(指向子类对象)来调用子类的这个函数
- 纯虚函数才代表函数没有被实现(函数原型后加“=0”),实现一个接口,规范继承这个类(即抽象类)的子类必须实现这个函数es
- 抽象类:含有纯虚函数的类
- 虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的,指明了实际所应该调用的函数。
- C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。
- https://blog.csdn.net/lyztyycode/article/details/81326699?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
虚函数与纯虚函数
- 虚函数是为了在运行时多态,父类提供虚函数的实现,为子类提供默认的函数实现,若子类重写虚函数,实现子类的特殊化,即多态的形式
- 存续函数没有函数实现,实现接口,规范子类实现这个纯虚函数
- 区别:
- 1.拥有虚函数的类不能成为抽象类,纯虚函数才可
- 2.虚函数可直接使用,或重载后被子类调用,但存虚函数只有子类实现后才能使用
虚继承
- 防止多重继承,造成数据冗杂
- 当重复继承时,只保留一个实例
https://blog.csdn.net/longlovefilm/article/details/80558879?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase
构造函数(无参数构造函数、拷贝构造函数)
- 无参数构造函数类中无定义的话,编译器默认提供,函数体为空
- 拷贝构造函数无定义,编译器默认提供,简单赋值,为浅拷贝
- 浅拷贝:物理状态相同
- 深拷贝:逻辑状态相同,对象成员使用系统资源,如:打开文件,动态分配内存空间
- 深拷贝必须重载赋值操作符
设计模式
- 二阶构造模式
- 二阶构造人为的将初始化过程分为两部分(不产生异常与可能产生异常地方)
- 杜绝半成品对象
- 单例模式
- 定义一个类,使得这个类最多创建一个对象
- 通过静态成员变量和友元来实现
STL中的智能指针auto_ptr
- 声明周期结束时,销毁指向的内存空间
- 不能指向堆数组,只能指向堆对象(变量)
- 一片堆空间只属于一个智能指针对象
- 多个智能指针对象不能指向同一片堆空间(避免多次释放同一指针)
- 很大程度上避开内存相关问题
构造函数、虚函数、析构函数
- 构造函数和析构函数可为虚函数,但不能发生多态行为(虚函数表指针未初始化,或已经销毁)
类型转换
- static_cast
- 基本类型转换
- 不能用于基本类型指针间转换
- 用于有继承关系类对象之间的转换和类指针之间的转换???- const_cast
- 用于去除变量的只读属性
- 范围目标类型必须是指针或引用
- reinterpret_case
- 用于指针类型间的强制转换
- 整数和指针类型间的强制转换
- dynamic_cast
- 用于有继承关系的类指针间的转换
- 需要虚拟函数的支持
- const_cast
const
- const Test t;只读对象,只能调用const成员函数,不可访问成员变量
C中const修饰的变量为只读变量
- 1、const修饰的局部变量,不能当左值,但可以通过指针进行修改。存在栈上只读变量
- 2、const修饰的全局变量(具有全局声明周期:如static修饰的局部变量),不可以当左值,不可以使用指针进行修改,否则会导致程序奔溃
- 3、const 本质修饰的是 只读变量,将变量放在只读存储区。
举例:
-
1) const int a;
-
2)int const a;
-
3)const int *a ;
-
4)int * const a;
-
5)int const * a const;
-
1)2)一样效果:定义一个整型指针不可赋值
-
3)a是一个指向常整型数的指针(整型数是不可修改的,但指针可以)
-
4)a是一个指向整型数的常指针(整型数是可修改的,但指针不可以)
-
5)a是一个指向常整型数的常指针(整型数是不可修改的,指针不可以)
volatile 防止“变化”
- 强制编译器减少优化,必须每次从内存中取值
- 使用场景:定时器,多线程共享和任务变量
- 多线程应用中被几个任务共享的变量
- 一个中断服务子程序中会访问到的非自动变量(全局变量、静态变量)
- 并行设备的硬件寄存器??(数据接收口)
- 举例:
- const volatile int i = 0;可以这样定义么?
- 可以的,这是容易被改变的值,去内存中取出来。而且不能放在等号左边进行修改。
- int square(volatile int *ptr)
{
return *ptr * *ptr;
} 定义有错误么?- 容易被外部中断或多线程更改,应该加个const。
- const volatile int i = 0;可以这样定义么?
Register
- 尽可能将变量存在CPU内部寄存器,提高效率
static
- 修饰局部变量,存静态存储区,作用域在局部函数内,但函数结束后不会被销毁
- 修饰全局变量,存静态存储区,普通全局变量其他文件可见,静态全局变量只对当前文件可见
- 用来修饰函数和变量,修饰函数之后,只能在本文件中明显调用,其他文件无法调用。
静态成员变量
- 静态成员变量隶属类所有
- 静态成员变量存储在全局数据区
- 静态成员变量的生命周期为程序运行周期
静态成员函数
- 静态成员函数属于整个类所有
- 可以通过类名或对象名访问公有的静态成员函数
- 静态成员函数没有隐藏的this参数,所以不能访问普通成员变量(函数)
- 静态成员函数只能直接访问静态成员变量(函数)
静态成员函数与普通成员函数
静态成员函数 | 普通成员函数 | |
---|---|---|
所有对象共享 | yes | yes |
隐含this指针 | no | yes |
访问普通成员变量 | NO | yes |
访问静态成员变量 | yes | yes |
通过类名直接调用 | yes | no |
通过对象名直接调用 | yes | yes |
C语言编译过程为:预处理–>编译–>汇编–>链接
内联函数
1.编译期间扩展到调用处
2没有入栈,跳转,返回的开销
3是个请求,可能不成功
4好处,参数和返回值得检查,取代宏代码块,高效
多看看
C++面试总结
https://blog.nowcoder.net/n/6a5c766a07f54582a6b7091fa3844691