✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/fYaBd
📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
19. 既 然有了 malloc/free,C++ 中为什么还需要 new/delete 呢?直接用 malloc/free 不好吗?
-
malloc/free 和 new/delete 都是用来申请内存和回收内存的。
-
在对非基本数据类型的对象使用的时候,对象创建的时候还需要执行构造函数,销毁的时候要执行析构函数。而 malloc/free 是库函数,是已经编译的代码,所以不能把构造函数和析构函数的功能强加给 malloc/free,所以 new/delete 是必不可少的。
20. C ++ 中有几种类型的 new?
在 C++ 中,new 有三种典型的使用方法:plain new,nothrow new 和 placement new
(1)plain new
言下之意就是普通的 new,就是我们常用的 new,在 C++ 中定义如下:
void* operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void *) throw();
因此 plain new 在空间分配失败的情况下,抛出异常 std::bad_alloc 而不是返回 NULL,因此通过判断返回值是否为 NULL 是徒劳的,举个例子:
#include <iostream>
#include <string>
using namespace std;
int main()
{
try
{
char *p = new char[10e11];
delete p;
}
catch (const std::bad_alloc &ex)
{
cout << ex.what() << endl;
}
return 0;
}
//执行结果:bad allocation
(2)nothrow new
nothrow new 在空间分配失败的情况下是不抛出异常,而是返回 NULL,定义如下:
void * operator new(std::size_t,const std::nothrow_t&) throw();
void operator delete(void*) throw();
举个例子:
#include <iostream>
#include <string>
using namespace std;
int main()
{
char *p = new(nothrow) char[10e11];
if (p == NULL)
{
cout << "alloc failed" << endl;
}
delete p;
return 0;
}
//运行结果:alloc failed
(3)placement new
这种 new 允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new 不用担心内存分配失败,因为它根本不分配内存,它做的唯一一件事情就是调用对象的构造函数。定义如下:
void* operator new(size_t,void*);
void operator delete(void*,void*);
使用 placement new 需要注意两点:
-
palcement new 的主要用途就是反复使用一块较大的动态分配的内存来构造不同类型的对象或者他们的数组。
-
placement new 构造起来的对象数组,要显式的调用他们的析构函数来销毁(析构函数并不释放对象的内存),千万不要使用 delete,这是因为 placement new 构造起来的对象或数组大小并不一定等于原来分配的内存大小,使用 delete 会造成内存泄漏或者之后释放内存时出现运行时错误。
举个例子:
#include <iostream>
#include <string>
using namespace std;
class ADT{
int i;
int j;
public:
ADT(){
i = 10;
j = 100;
cout << "ADT construct i=" << i << "j="<<j <<endl;
}
~ADT(){
cout << "ADT destruct" << endl;
}
};
int main()
{
char *p = new(nothrow) char[sizeof ADT + 1];
if (p == NULL) {
cout << "alloc failed" << endl;
}
ADT *q = new(p) ADT; //placement new:不必担心失败,只要p所指对象的的空间足够ADT创建即可
//delete q;//错误!不能在此处调用delete q;
q->ADT::~ADT();//显示调用析构函数
delete[] p;
return 0;
}
//输出结果:
//ADT construct i=10j=100
//ADT destruct
21. delete p、delete[] p、allocator 都有什么作用?
1、 动态数组管理 new 一个数组时,[] 中必须是一个整数,但是不一定是常量整数,普通数组必须是一个常量整数;
2、 new 动态数组返回的并不是数组类型,而是一个元素类型的指针;
3、 delete[] 时,数组中的元素按逆序的顺序进行销毁;
4、 new 在内存分配上面有一些局限性,new 的机制是将内存分配和对象构造组合在一起,同样的,delete 也是将对象析构和内存释放组合在一起的。allocator 将这两部分分开进行,allocator 申请一部分内存,不进行初始化对象,只有当需要的时候才进行初始化操作。