前言
new这个关键字,贯穿于我们所有c++代码中,我们知道他是申请了一块内存给我们开发人员用,但是其中发生了什么?很多人都不得而知,本文就让我们一起研究一下new。
new的作用
大家在定义一个对象或者指针的时候,会不会有这么的疑问?
ClassA a;
ClassA *b = new ClassA();//这两种方式有什么区别
首先对象和指针的区别,在前文研究指针的时候,我们已经了解过,具体可以参照博客:c++基本语法之一二三(1)-初识指针
这部分就不再赘述,但是为什么不能写成这个方式呢?
ClassA a;
ClassA *b = &a;//这两种方式有什么区别
这种方式定义的b指针和上面定义的b指针有什么区别吗?
答案是:第一种b指针指向对象内存是存放在堆内存中,第二种b指向了a的内存首地址,而a的内存是存放在栈中的,而堆栈之间的具体区别,我准备专门在另一篇研究c++内存分布的文章中细细研究~,而现在我们只需要知道堆内存是由开发人员自己控制的一部分内存,如果开发人员申请之后不自己释放的话,那么这块内存会一直被占用,这也就是内存泄漏问题的最常见的原因,那么栈内存会在超出变量作用域的时候由编译器自动释放。
而new关键字的作用就是申请一块堆内存,然后返回这块堆内存的首地址。
new可以称为new operator,也就是new,其中new可以分为两部分,operator new和placement new,下面我们分别研究一下。
operator new
operator new的作用是申请一块堆内存,但也仅仅是申请一块堆内存,并没有构造对象的过程,来看代码
#pragma once
#include <iostream>
class base
{
public:
int privateValue;
public:
void* operator new(size_t _Size)
{
std::cout << "此时operator new被调用" << std::endl;
return (void*)malloc(_Size);
}
};
然后,我们new这么一个对象
#include <iostream>
int main()
{
base* ptr = nullptr;
ptr = new base();
delete ptr;
}
此时,我们看一下输出结果:

我们发现,编译器调用了我们类中重写的operator new函数,并没有用全局的operator new函数,这就引出我们的一个结论:若在new一个类对象时,类中如果重写了operator new,则用类自定义的,若没有,则用全局的。
placement new
使用operator new申请到一块堆内存之后,我们还需要做什么事呢?是不是需要将我们的对象在这块内存中分布起来,也就是我们买了一套房子,现在我们的住户需要搬进去了,我们改一下.h的代码,来看:
#pragma once
#include <iostream>
class base
{
public:
int privateValue;
public:
void* operator new(size_t _Size)
{
std::cout << "此时operator new被调用" << std::endl;
return ::operator new(_Size);
}
void* operator new(size_t _Size,void *ptr)
{
std::cout << "此时placement new被调用" << std::endl;
return ::new(ptr)base();
}
};
int main()
{
int a;
base* ptr = new((void *)&a) base;
}
来看结果:

此时调用了类重写的placement new函数,而这个函数实际上也就是operator new的另一个重载版本,函数原型为:void* operator new(size_t _Size,void* ptr) ;这个函数的作用是在ptr指向的内存中构造对象。但是此时构造函数却被调用了两次,这个问题比较奇怪~
想一想,这可以在我们的实际开发中有什么作用?我们在现有的内存位置中构造对象,能够减少程序对内存的申请,从而减少整个程序的资源占用。
小结
1.new可以称为new operator,也就是new,其中new可以分为两部分,operator new和placement new。
2.operator new的作用是申请一块堆内存,并返回内存的首地址。
3.placement new的作用是在指定的内存位置中构造对象。
4.其他:operator new对应的有operator delete,placement new 对应placement delete,其中delete操作符的调用顺序与new相反,也就是先调用placement delete,然后再调用operator delete,其中placement delete仅仅只调用析构函数,而不对内存有操作,operator delete会释放所对应的内存块,这里不多做解释。
477

被折叠的 条评论
为什么被折叠?



