C++ new和delete内存分配
在C语言中我们使用的是malloc与free函数来分配内存,但Malloc分配内存需要自己定义分配的长度,这样十分不方便,于是c++中推出了new与delete来将对象放置在特定的内存空间中,它能够自动根据分配内存的对象分配内存大小。
基本操作
string a = new string; //分配一个string类型的对象
string *b= new string[10]; //分配10个默认初始化的string对象
delete a;
delete [] b; //删除数组要加[]
内存分配分为三个步骤:
步骤 | 操作 |
---|---|
1 | new 表达式调用函数库中 operator new (或operator new [ ])函数分配一块原始空间,在这块空间中中没有任何东西,只是一个容器, |
2 | 编译器运行相应的构造函数构造相应对象,传入初值 |
3 | 返回指向对象的指针 |
内存的销毁分为两个步骤
步骤 | 操作 |
---|---|
1 | 调用相应的析构函数将内存中的对象析构 |
2 | 编译器调用operate delete [ ](或operator delete)释放内存空间 |
中级操作
我们可以不通过new与delete来一步实现,而是通过手动一步步实现,在实际应用当中这样做也是有实际意义的:
class A
{
pubilc:
A(int a);
~A();
}:
实际项目中,并不是每个类都是需要默认构造函数的,只有当类中初始化的变量有意义时我们才会写默认构造函数,但假如这个类初始化是没有任何意义的时候(比如仪器公司规定每一个生产仪器都需要有一个编号,如果没有编号,这个仪器就毫无意义),那么我们的构造函数都需要一个变量。
但没有默认构造函数我们的程序就会变得比较难写
A a[10];
A *a = new A[10];
因为没有默认构造函数,所以这种写法无法编译,假如我们需要创建一个类的数组需要用下面这种方式创建
class A
{
public:
A(int a){
std::cout << "call A constructor" << std::endl;
}
~A(){
std::cout << "call A destructor" << std::endl;
}
};
int main()
{
void *RawMomery = operator new[](10 * sizeof(A)); //第一步开辟一个10*A大小的内存空间
A *Basement = static_cast<A *>(RawMomery); //转换RawMomery数据类型为*A并赋值给basement
for (int i = 0; i < 10; i++) {
new(&Basement[i]) A(1); // placement new (能够定位放置new):在BaseMent[i]处创建A(1)
}
for (int i = 0; i < 10; i++) {
Basement[i].~A(); //析构BaseMent数组中的元素
}
operator delete[](RawMomery); //释放内存
return 0;
}
这么做可以提高class效率,防止无意义字段产生。
高级操作
C++是一门非常灵活的语言,它还可以通过自定义opeartor new与operator delete函数对内存分配的过程进行控制。当编译器找到一个new或delete函数的时候,就会查找整个程序中的operator new(operator delete)函数(先在类与基类中查找,之后在全局作用域查找)找到则使用 我们自己写的函数(使用::new或::delete可直接在全局作用域查找)
class A
{
public:
A(int a){
std::cout << "call A constructor" << std::endl;
}
void *operator new (size_t size);
void operator delete(void *dead ) noexcept;
~A(){
std::cout << "call A destructor" << std::endl;
}
};
void *A::operator new(size_t size ){
cout << "调用了A::operator new " <<endl;
A *p=(A*)malloc(sizeof(A));
return p;
}
void A::operator delete(void *dead) noexcept {
cout << "调用了A::operator delete" << endl;
free(dead);
}
int main()
{
A *p = new A(1);
//A *p = ::new A(1);
delete p;
//::delete p;
return 0;
}
如果有什么不足,希望大佬指正