C++面试题总结(更新中)

虚函数和纯虚函数

1.父类中不加virtual,子类也可以重写,但这样做意义不大,一般子类只会重写父类的虚函数和纯虚函数。
2.虚函数和纯虚函数的区别:
虚函数在父类中有函数体,纯虚函数没有函数体,纯虚函数如virtual void test() = 0
某些情况下父类中此虚函数的函数体实现没有意义,就会用纯虚函数。
一个继承类中必须实现所有的纯虚函数才能实例化,否则无法实例化。

重载和重写

重载:是指允许存在多个同名函数,而这些函数的参数表不同。只有返回值类型不同不算重载。
重写:是指子类重新定义父类虚函数的方法。
重载是在类内部的,重写发生在子类与父类之间。

指针和引用的比较

引用必须被初始化,指针不必。
引用初始化以后不能被改变,指针可以改变所指的对象。
引用只是别名,不占用内存单元。

const与#define的比较

const常量有数据类型,而宏常量没有数据类型。
编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查。

基类的析构函数为什么要设计为虚函数

在设计类时如果这个类是基类,那么就需要将这个类的析构函数设计为虚函数。
如果这个类是派生类,不会再作为基类,那么就不需要将这个类的析构函数设计为虚函数。

基类的析构函数只有设计为虚函数,子类的析构才能实现多态,才能在析构时销毁每个子类独有的资源,否则只能销毁基类的资源无法销毁子类的资源,造成资源的泄漏。

类的构造函数为什么不能是虚函数

假设A-B是父类-子类的关系,根据虚函数的性质,若是A的构造函数为虚函数,且B类也给出了构造函数,则应该只执行B类的构造函数,再也不执行A类的构造函数,这样A就不能构造了。
另外virtual函数是不一样的类型的对象产生不一样动作,如今对象还没产生,如何使用virtual函数来完成你想要的动作。

内存模型

全局/静态存储区、堆、栈、代码区、常量区

全局变量和局部变量:全局变量在全局存储区,局部变量在栈上,
操作系统和编译器通过内存分配的位置可以知道是全局变量还是局部变量。

内联函数

1.普通函数
调用过程有参数压栈,函数栈帧的开销和回退等,存在函数调用的开销。

2.inline函数
在编译过程中,没有函数调用的开销,在函数的调用点直接把函数的代码进行展开处理
inline函数不再生成相应的函数符号,而普通函数会生成函数符号,如int sum(int a, int b);会生成sum_int_int的函数符号。
并不是所有的inline函数都会被编译器处理成内联函数(如递归)。
在debug版本中,inline不起作用,只有在release版本中起作用。
注意:函数被声明为内联函数,只是建议编译器处理成内联函数,是否处理成内联函数由编译器决定。

野指针

野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
野指针与空指针(NULL)不同,空指针在C语言中定义为 #define NULL ((void *)0)
可见空指针指向0地址,而野指针指向不确定的地方。野指针产生主要有两个原因:
1、指针变量未初始化:任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。
2、指针释放之后未置空:使用free或delete只是把指针所指的内存释放掉,但不会把指针删除,需要手动置NULL。

const

const作用就是将变量变成常量。
1.常变量
	变量用const修饰,其值不得被改变。任何改变此变量的代码都会产生编译错误。
	const加在数据类型前后均可,const int a 或 int const a。
2.常指针
	const跟指针一起使用的时候有两种方法,一种是限制指针不可变,一种是限制指针指向的内容不可变。
	char* const a;			指针的值不可变
	const char* a;			指针指向的内容不可变
	const char* const a;	指针指向的内容和指针的值都不可变
3.常引用
	引用就是变量的别名,常引用的话就是不能改变这个变量的内容。
	int a = 0;
	const int &r = a;
	r = 1; //错误,不能改变内容了
4.const和函数
	const放在函数后通常是用在类中,限制类的成员函数不能对成员变量进行修改,也不能调用类中非const的函数。
	const放在函数前是限制函数的返回值是指针时,指针指向的内容不能被修改。

static

1.static-全局
static修饰全局变量或全局函数时,此全局变量或全局函数只在当前文件可见,在文件外不可见。

2.static-局部
static修饰局部变量时,此变量会变成静态变量,会存储在全局/静态存储区,只会初始化一次。

3.static-类的静态成员变量
类的静态变量即是在类中,用关键字static声明成员变量。
无论建立了多少个对象,都只有一个静态变量的拷贝。
静态成员变量,不属于某一个类对象,而只是属于这个类,对于所有类对象时共享的。
->类的静态成员变量,必须在类中声明、在类外定义。
->类的静态成员变量,既可以通过类对象访问,也可以通过类名直接访问。

4.static-类的静态成员函数
在类定义中,用static声明的成员函数为静态成员函数。
使用方式与静态成员变量一样,都是通过类对象访问和类名直接访问。
类的静态成员函数的意义在于管理静态成员变量,完成对静态成员变量的封装。
->静态成员函数只能访问静态成员变量,不能访问普通成员变量。
->普通成员函数可访问静态成员变量,也可以访问普通成员变量。

构造函数和析构函数

构造函数不能是虚函数;基类的析构函数必须是虚函数。

子类实例化时:Son *s = new Son(); delete s; 父类构造-子类构造-子类析构-父类析构
子类提升时:Parent *p = s; delete p; 此时析构函数必须是虚函数,否则子类的析构无法实现多态、只能销毁父类资源无法销毁子类资源。

为什么要有字节对齐

CPU访问内存并不是一个字节一个字节访问,而是按照2个字节、4个字节、8个字节、16个字节、32个字节这种2的倍数来访问的。
因此就需要字节对齐,否则可能造成一个简单的数据类型如int(4个字节)需要从两个存储单元读取再合并,这样就会降低效率。
struct {
	char a;
	char b;
	int c;
}s;
上述的结构体占8个字节,通过sizeof(s)可以计算。

32位和64位

32位系统的指针类型大小为4byte,64位系统的指针类型大小为8byte。
32 / 8 = 4
64 / 8 = 8

32位系统进程的虚拟寻址空间为4GB		2 ^ 32 = 4GB
64位系统进程的虚拟寻址空间可达		2 ^ 44 = 8TB(被限制到了44位,达不到64位)

C++函数栈空间的最大值

和系统以及编译器选项有关。
Linux每个线程的栈默认大小是8MB,Windows每个线程的栈默认大小是1MB。
上述栈的大小可以通过编译器的选项来修改。VS工程上可以在"属性-输入-系统-栈空间大小"来修改。
栈是线程的概念,不是进程的,所以要说每个线程的栈默认大小。

vector和list区别

1.vector:动态数组,list:双向链表
2.vector底层实现是数组;list是双向链表。
3.vector支持随机访问,list不支持。
4.vector在中间节点进行插入删除会导致内存拷贝,list不会。
5.vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。
6.vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。
7.vector拥有一段连续的内存空间,因此支持随机访问,如果需要高效的随机访问,而不在乎插入和删除的效率,使用vector。
8.list拥有一段不连续的内存空间,如果需要高效的插入和删除,而不关心随机访问,则应使用list。

迭代器和指针的区别

用迭代器可以很大程度上隔离容器底层实现,使用时只需依赖迭代器相对统一的方法/接口。
用指针需要依赖容器底层实现细节。

struct和class区别

1.C++是向C兼容的,因此C++中保留了struct。
2.C++相比与C中的struct,扩展了功能,包括:
	可以包含成员函数
	可以实现继承、多态
3.C++中struct与class
	struct的访问权限和继承权限默认都是public
	class的访问权限和继承权限默认都是private

几种必须在类初始化列表中进行初始化的情况

1.类成员为const类型
原因:const对象一旦创建后其值就不能改变,所以const对象必须初始化。

2.类成员为引用类型
原因:const对象和引用类型都只能初始化而不能赋值。构造函数体内只能实现赋值,初始化列表是初始化这两种类型成员的唯一机会。
初始化和赋值是不同的概念:初始化调用拷贝构造函数创建新对象,而赋值调用赋值运算符对已有对象进行赋值。

3.类成员为没有默认构造函数的类类型(类成员为重写了构造函数的类类型)
原因:因为这类成员没有默认构造函数(=default),所以只能在初始化列表中调用它的“实际”构造函数进行初始化。
注:如果你重写了类的构造函数的话,编译器就不会为你添加默认的空的构造函数了。

4.派生类必须在初始化列表中调用基类构造函数
原因:每个类控制它自己的成员初始化过程,派生类需要调用基类构造函数初始化自身继承的基类部分。

#include <> 和 #include “”

#include <> 的查找位置是标准库头文件所在目录, 
#include "" 的查找位置是当前源文件所在目录,查找不到的话再会去查找标准头文件所在目录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值