面试题

1. malloc/free和new/delete的区别

共同点:

  1. 都是从堆上申请空间。并且需要用户手动释放

不同点:

  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以
  3. malloc申请空间时,需要手动计算空间的大小并传递,new只需要在其后边跟上空间的类型即可
  4. malloc的返回值是void*,在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc在申请失败后返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理 (上篇博客讲过)
  7. new/delete比malloc和free的效率稍微低点,因为new/delete的底层封装了malloc/free

2.请设计一个类。该类只能在堆上创建对象

做这道题要清楚,哪些变量在堆上,哪些变量在栈上???

栈:就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。

堆:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。比如说,在c中malloc函数如p1 = (char )malloc(10);在C++中用new运算符如p2 = (char )malloc(10);但是注意p1、p2本身是在栈中的

解决方法:

  • 构造函数私有化
    1. 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
    2. 提供一个静态成员函数,在该静态成员函数中完成堆对象的创建。
class HeapOnly
{
public:
	static HeapOnly* CreatObject()
	{
		return new HeapOnly;
	}
private:
	HeapOnly()
	{}
	//C++98
	HeapOnly(const HeapOnly&);
	//或者C++11
	HeapOnly(const HeapOnly&) = delete;

};

3.请设计一个类,该类只能在栈上创建对象

class StackOnly
{
public:
	static StackOnly CreateObject()
	{
		return StackOnly;
	}
private:
	StackOnly()
	{}
};

只能在栈上创建对象,即不能在堆上创建,因此只要将new的功能屏蔽掉即可,即屏蔽掉operator new和定 位new表达式,注意:屏蔽了operator new,实际也将定位new屏蔽掉。

4.单例模式(这个在面试中经常出现)

单例模式:

一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全 局访问点,该实例被所有程序模块共享。

单例模式有两种实现模式:

  • 饿汉模式
    就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。

优点:简单
缺点:可能会导致进程启动慢。且如果有多个单例类对象实例启动顺序不确定

5.内存泄漏

  • 什么是内存泄漏?

内存泄漏是指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

void MemoryLeaks()
{
	//1.内存申请了忘记释放
	int* p1 = (int*)malloc(sizeof(int));
	int* p2 = new int;

	//2.异常安全问题
	int* p3 = new int[10];

	Func();// 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放

	delete[] p3;
}
  • 内存泄漏分类

C/C++程序中一般我们关心两种方面的内存泄漏:

  1. 堆内存泄漏(Heap leak)

堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存, 用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那 么以后这部分空间将无法再被使用,就会产生Heap Leak

  1. 系统资源泄漏

指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统 资源的浪费,严重可导致系统效能减少,系统执行不稳定。

  • 如何检测内存泄漏
    C/C++动态内存管理的相关面试题合集_内存泄漏
  • 如何避免内存泄漏

内存泄漏非常常见,解决方案分为两种:
1、事前预防型。如智能指针等。
2、事后查错型。如泄漏检测工具。

6.如何一次在堆上申请4G的内存?

#include<iostream>
using namespace std;

int main()
{
	void* p = new char[0fffffffful];
	cout << "new:" << p << endl;
	return 0;
}