大家好,我是帅地。
上次我更新了一整套 Java 面试题,没看过的可以我个人网站看:www.iamshuaidi.com。
也有一些人来催我更新 C++ 的面试题,刚好在正值校招,所以最近也在整理 C++ 的面试题,不过目前只整理的几十道,因为网上的面试题参差不齐,找起来不是很好找。
不过帅地会争取在这一个月内找齐的,方便大家复习,更多面试题可以看文末。
new/delete
可以调用对象的构造函数和析构函数,属于运算符,在编译器权限之内;malloc/free
仅用于内存分配和释放,属于库函数,不在编译器权限之内;new
是类型安全的,而malloc
返回的数据类型是void *
,所以要显式地进行类型转换;new
可以自动计算所需字节数,而malloc
需要手动计算;new
申请内存失败时抛出bad_malloc
异常,而malloc
返回空指针。对于简单类型来说,使用new
分配后,不管是数组数组还是非数组形式,两种方式都可以释放内存:
int *a = new int(1);
delete a;
int *b = new int(2);
delete [] b;
int *c = new int[11];
delete c;
int *d = new int[12];
delete [] d;
对于自定义类型来说,就需要对于单个对象使用delete
,对于对象数组使用delete []
,逐个调用数组中对象的析构函数,从而释放所有内存;
如果反过来使用,即对于单个对象使用delete []
,对于对象数组使用delete
,其行为是未定义的;
所以,最恰当的方式就是如果用了new
,就用delete
;如果用了new []
,就用delete []
。
malloc
和new
返回空指针,该怎么处理?对于malloc
来说,需要判断其是否返回空指针,如果是则马上用return
语句终止该函数或者exit
终止该程序;
对于new
来说,默认抛出异常,所以可以使用try...catch...
代码块的方式:
try {
int *ptr = new int[10000000];
} catch(bad_alloc &memExp) {
cerr << memExp.what() << endl;
}
还可以使用set_new_handler
函数的方式:
void no_more_memory() {
cerr << "Unable to satisfy request for memory" << endl;
abort();
}
int main() {
set_new_handler(no_more_memory);
int *ptr = new int[10000000];
}
在这种方式里,如果new
不能满足内存分配请求,no_more_memory
会被反复调用,所以new_handler
函数必须完成以下事情:
new_handler
第一次被调用,就将这些内存释放还给程序使用;new_handler
:返回空指针,这样new
就会抛出异常;abort
或exit
。内存泄漏的场景:
malloc
和free
未成对出现;new/new []
和delete/delete []
未成对出现;
char* getMemory()
{
char *p = (char *)malloc(30);
return p;
}
int
main()
{
char *p = getMemory();
return
0;
}
未定义拷贝构造函数或未重载赋值运算符,从而造成两次释放相同内存的做法;比如,类中包含指针成员变量,在未定义拷贝构造函数或未重载赋值运算符的情况下,编译器会调用默认的拷贝构造函数或赋值运算符,以逐个成员拷贝的方式来复制指针成员变量,使得两个对象包含指向同一内存空间的指针,那么在释放第一个对象时,析构函数释放该指针指向的内存空间,在释放第二个对象时,析构函数就会释放同一内存空间,这样的行为是错误的;
没有将基类的析构函数定义为虚函数。
判断和定位内存泄漏的方法:在Linux系统下,可以使用valgrind、mtrace等内存泄漏检测工具。
new
分配/delete
释放的内存块,也称为动态内存分配,程序员自行申请和释放内存,使用灵活;malloc
分配/free
释放的内存块,与堆类似;alloca()
函数进行分配,但是会由编译器释放;new/delete
或者malloc/free
会造成内存空间的不连续,产生大量碎片,是程序效率降低;private
;new
和delete
重载为private
。浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享一块内存;而深拷贝会创造一个相同的对象,新对象与原对象不共享内存,修改新对象不会影响原对象。
#pragma pack(n)
sizeof
的最终结果必然是结构内部最大成员的整数倍,不够补齐;#pragma pack(n)
sizeof
的最终结果必然必然是min[n,结构内部最大成员]
的整数倍,不够补齐;min[n,自身大小]
的整数倍。由于公众号没有目录,阅读体验可能不大好,所以呢,更多面试题可以在我个人网站阅读哦。 C++面试题:https://www.iamshuaidi.com/2309.html
ps:点击阅读原文可直达,不过建议PC端阅读