0.static、const、volatile的作用和区别
static:
https://www.cnblogs.com/Manual-Linux/p/8870038.html
第一、在修饰变量的时候,static修饰的静态局部变量只执行一次,之后再初始化无效。而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
第二、static修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以。
第三、static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。Static修饰的局部变量存放在全局数据区的静态变量区。初始化的时候自动初始化为0
const:
1.修饰的变量只读,不可改变
2.防止意外修改,减少bug
3.可以节省空间,避免不必要的内存分配
volatile:
告诉编译器这个变量随时可变,不需要优化
1.请问全局变量和局部变量能否重名
能,局部会屏蔽全局。要用全局变量,需要使用"::"
2. 用三目运算符(X)>(Y)?(X):(Y)宏定义实现比较两个数的大小
#define MAX(X, Y) ((X)>(Y)?(X):(Y))
3.malloc的了解
malloc是动态内存分配,是用户动态申请系统分配指定字节的内存块的函数。返回类型是 void* 类型
对应free, 释放ptr指向的存储空间
4.new和malloc的区别
参看:https://blog.csdn.net/weixin_40535588/article/details/90110493
5.模拟实现strcpy,strcat,strcmp,strstr,memcpy
https://blog.csdn.net/studyhardi/article/details/84062485
6.用宏来计算偏移量,判断大小端(联合体法,指针法)
https://blog.csdn.net/studyhardi/article/details/83957869
7.i++是否为原子操作?
不是。操作系统原子操作是不可分割的,在执行完毕不会被任何其它任务或事件中断,分为两种情况(两种都应该满足)
(1) 在单线程中, 能够在单条指令中完成的操作都可以认为是" 原子操作",因为中断只能发生于指令之间。
(2) 在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
i++分为三个阶段:内存到寄存器 寄存器自增 写回内存
这三个阶段中间都可以被中断分离开.
8. C++中类与结构体的区别?
最本质的一个区别就是默认的访问控制: struct作为数据结构的实现体,它默认的数据访问控制是public的,而class作为对象的实现体,它默认的成员变量访问控制是private的。
9.析构函数的作用?
用来释放所定义的对象消亡时,自动被调用,用来释放对象占用的空间,避免内存泄漏对象中使用的指针
10.虚函数的作用?
虚函数可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时,基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,而不是基类中定义的成员函数(只要派生类改写了该成员函数)。若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都会调用基类中定义的那个函数。虚函数是C++多态的一种表现,可以进行灵活的动态绑定。
11.什么是纯虚函数
纯虚函数就是没有函数体,同时在定义的时候,其函数名后面要加上“= 0”。
虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)只有声明而没有定义。
12. 类模板
类模板,可以定义相同的操作,拥有不同数据类型的成员属性。
通常使用template来声明。告诉编译器,碰到T不要报错,表示一种泛型.
https://blog.csdn.net/zhuzhaoming1994/article/details/80346250
13.什么是C++的多态性
1.多态性可以简单地概括为“一个接口,多种方法”,
2.C++支持两种多态性:编译时多态性,运行时多态性。
a、编译时多态性:通过重载函数实现 b、运行时多态性:通过虚函数实现。
3.C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。
14..什么情况下需要将析构函数定义为虚函数?
当基类指针指向派生类的对象(多态性)时。如果定义为虚函数,则就会先调用该指针指向的派生类析构函数,然后派生类的析构函数再又自动调用基类的析构函数,这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。所以,将析构函数声明为虚函数是十分必要的。
15.重载与重写的区别?
从定义上来说:重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。重写:是指子类重新定义父类虚函数的方法。
16.volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化(编译器自己假设)而省略,且要求每次直接读值
17.volatile和const可以同时使用吗?
可以, 如果一个变量不会被本程序改变,通常可能给它加上const,但如果该变量可能被其他程序改变而本程序又在检测这个变量的值,就需要给它加上volatile
18.联合体union的基本特性——和struct的同与不同
结构体(struct)中所有变量是“共存”的——全面;缺点是struct内存空间是全分配。
而联合体(union)中是各变量是“互斥”的——缺点就是变量共用首地址,一个值变,另外变量会跟着变;但优点是内存使用更为精细灵活,也节省了内存空间。
19.为什么要结构体内存对齐
平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存访问仅需一次访问。(对齐的地址的数据容易访问)
如int要在4的倍数地址分配,char分配后要空闲地址到4的倍数的地址
20.位域是什么
所谓“位域”是把一个字节中的二进位划分为几 个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。位段成员必须声明为int、unsigned int或signed int类型(short char long)。
21.什么是可重入函数
可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误
可重入的函数必须满足以下三个条件:
(1)可以在执行的过程中可以被打断;
(2)被打断之后,在该函数一次调用执行完之前,可以再次被调用(或进入,reentered)。
(3)再次调用执行完之后,被打断的上次调用可以继续恢复执行,并正确执行
22.防止H文件被重复包含的处理方法
#ifndef _H文件名_H_
#define _H文件名_H_
//H文件内容
#endif
23.内存溢出,内存泄漏,数组越界的原因?
溢出 out of memory,分为栈溢出和内存溢出,栈溢出是指函数中的局部变量超过栈最大值造成的溢出,内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
内存泄漏比内存溢出危害性更大
内存溢出的解决方案:
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
数组越界:
char a[9]={0};
cout << a[9] << endl;
24.const和define
const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
25.sizeof 和 strlen 的区别
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;
26.C、C++中内存分配方式有哪些
C、C++中内存分配方式可以分为三种:
(1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。
(2)在栈上分配:在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配:即动态内存分配。程序在运行的时候用 malloc 或 new 申请任意大小的内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。
27.面向对象的三大特征
① 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
② 继承,是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”和“组合”来实现。
③ 多态,简单的说,就是一句话:允许将指向子类类型的指针赋值给父类类型的指针。实现多态,有二种方式,覆盖,重载。
覆盖,是指子类重新定义父类的虚函数的做法。
重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)
28.引用和指针区别
① 引用必须被初始化,但是不分配存储空间,其实就是同一个数据。指针是存储了指向的对象的地址,在初始化的时候需要分配存储空间
② 引用初始化以后不能被改变,指针可以改变所指的对象
③ 不存在指向空值的引用,但是存在指向空值的指针
30.数组指针和指针数组,函数指针的区别
数组指针 定义 int (*p)[n];指向一个数组对象的指针
指针数组 定义 int *p[n]; 是一个存放多个指针的数组
函数指针 是一个存放函数地址的指针
int func(int x); /* 声明一个函数 */
int (*f) (int x)=&fun或 int (*f) (int x)=fun; /* 声明一个函数指针 */
31.表示数组a第i行第j列a[i][j]的方法
3种
*(a[i]+j) *(*a+i)+j) (*(a+i))[j]
地址和指针
32.const int *a 和 int * const a 区别
const int * a:const修饰的是整型数 int,而不是指针,即a是一个指向常整型数的指针。近一步的理解为:整型数 *a是不可以被重新赋值的,而指针却是可以修改的
int * const a:const修饰的是指针a,而不是整型数*a,*a为变量而不是一个常量。即a是指向一个可以修改的整型数的常指针。进一步的理解为:指针指向的整型数是可以被修改的,但是指针不可以被修改。
总结:const离谁近,谁就不可以被修改
参看:https://blog.csdn.net/leikun153/article/details/80147657
33.怎么将程序跳转到指定内存地址
要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234;那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
首先要将0x100000强制转换成函数指针,及 (void (*)())0x100000,在调用他*((void (*)())0x100000)();
34. 抽象类和接口的区别
在C++里面抽象类就是接口
抽象类:定义了纯虚函数的类是抽象类,不能实例化。
抽象类包括抽象方法(纯虚方法),也可以包含普通方法。
抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖。
虽不能定义抽象类的实例,但是可以定义抽象类的指针。
35. 什么时候用常引用
const int &ra = a; // 不能通过引用对目标变量的值进行修改,从而使引用的目标成为const的,安全。
36.有几种情况用intialization list(初始化列表)而不是assignment(赋值)
1.对于const和reference类型成员变量,它们只能够被初始化而不能做赋值操作,因此只能用初始化列表
2..需要初始化的数据成员是对象的情况;
3.C++的引用也一定要初始化,所以必须在初始化列表中完成。
4.调用一个基类的构造函数,而该函数有一组参数
37.main函数之前会执行什么代码?
全局变量的初始化。
38.数组和指针的区别
数组要么在静态存储区创建,要么在栈上创建。指针可以随时指向任意类型的内存块。
39.为什么基类的析构函数是虚函数?
动态绑定,不会造成潜在的内存泄漏
40.友元函数
友元函数访问对象中的成员要通过对象名
41.switch参数类型
可以是:byte short int long bool
不能是: float double(这种浮点型的不能精确的比较,所以不能) string
但是在c++ 11里面, string可以作为switch的条件了。
42.C++ 内联
是代码嵌套,而不是调用
43.C++函数传参数方式
值传递、指针、引用
44.#include<file.h> #include "file.h" 区别
前者是从标准库路径寻找
后者是从当前工作路径
45.什么是c++的空类
空类,声明时编译器不会生成任何成员函数
对于空类,编译器不会生成任何的成员函数,只会生成1个字节的占位符。
有时可能会以为编译器会为空类生成默认构造函数等,事实上是不会的,编译器只会在需要的时候生成6个成员函数:一个缺省的构造函数、一个拷贝构造函数、一个析构函数、一个赋值运算符、一对取址运算符和一个this指针。
46.extern "C "指使用c语言的方法定义
47. C ++ 在c基础上加了什么?
A:包含全部的C语言部分。
B:面向对象部分,封装,继承,多态。
C:泛型编程部分,模板,方便使用。
D:STL库。
STL库:https://blog.csdn.net/qq_38880380/article/details/78360799
https://blog.csdn.net/weixin_40535588/article/details/89815453
48.空指针和悬挂指针
空指针是等于null的指针; 悬挂指针是delete后没有置空的野指针。