美文网首页
C++ 内存操作new & delete

C++ 内存操作new & delete

作者: 我阿郑 | 来源:发表于2021-12-21 09:48 被阅读0次

一、new & delete

回顾malloc/freemalloc申请而来的只是内存,严格地说并不是“对象”

// 4个int , 16个字节
int* p = (int*) malloc(16);
for(int i=0; i<4; i++){
    p[i] = i;
}
free(p);

在C++中,用new/delete操作符取代malloc/free

// 申请一个对象 :
int*  p = new int; 
delete  p; // 释放

// 申请多个对象 :例如,申请1024个int对象
int*  p = new int [1024] ;
delete []  p;

// 申请一个int, 一个double

int* p1 = new int;
*p1 = 12;
delete p1; // 用完后释放 

double p2 = new double(12.34);
printf("%f \n", *p2);
delete p2; // 用完后释放

// 申请一个Student对象
Student* s = new Student;
s->id = 12;
strcpy(s->name, "shaofa");
// 用完之后,释放
delete s;

//申请一个长度为10000的char数组,填充为1,2,3,...
char*  arr = new char [10000];
for(int i=0; i<10000; i++)
{
    arr[i] = i + 1;
}
delete [] arr;

注意:

  • new的返回值直接就是对象指针,不用再转换
  • new的时候可以设初始值 new int(12);
  • 用new申请的内存,必须用delete释放
  • 如果new的时候用了[],则释放的时候使用delete []操作符

和free一样,delete之后指针所指向的内存不再可用

delete p;
p = nullptr; // 最好置为空指针

动态创建对象

对于class类型,必须用new/delete来创建、销毁。
malloc/free是无法胜任的

new:动态创建一个对象:

  • 申请一块内存
  • 内部调用了构造函数

delete:释放这个对象:

  • 调用了析构函数
  • 释放内存
// 动态创建一个对象
// new的时候构造函数被调用,delete的时候析构函数被调用
Circle* c = new Circle(); // 默认构造函数
Circle* c = new Circle; // 不加括号也可以
Circle* c = new Circle(1,1,4); // 传构造参数
delete c;


// 动态创建多个对象
// ⚠️ 含有“默认构造函数”的类,才可能使用new []一次性地创建多个对象
Circle* c = new Circle[4];
delete [] c;

new与malloc的最大区别

new和malloc巨大区别:

  • malloc返回的只是一片内存、不是对象(malloc不负责构造)
  • new返回的是一个可以正常工作的对象(因为它调用了构造函数)

所以,new/delete 不仅仅时申请内存这么简单,它是申请了内存,并且构造了对象

Circle* p = (Circle*)malloc(sizeof(Circle));
// 强转为Circle* ??? 没用,因为没有调用构造函数

double area = p->GetArea(); // !!! 对象不可用

小结

  • new得到的是一个对象,malloc得到的不是对象 。因此,C++的类必须用new,不能用malloc

  • new一个对象的时候,可以传参,内部会调用构造函数。

  • new多个对象(数组)的时候,不能传参数,要求该类必须有默认构造函数

二、用new创建类对象与不用new的区别

  • new创建类对象需要指针接收
  • new创建类对象使用完需delete销毁
  • new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
  • new对象指针用途广泛,比如作为函数返回值、函数参数等
  • 频繁调用场合并不适合new,就像new申请和释放内存一样
// 1. 使用new创建对象
// new申请的对象,则只有调用到delete时再会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏
CTest* pTest = new CTest();
delete pTest;

// 2. 不使用new,直接使用类定义声明
// 此种创建方式,使用完后不需要手动释放,该类析构函数会自动执行
CTest mTest;

// 例如:
#include <iostream>
using namespace std;
 
class A
{
private:
    int n;
public:
    A(int m):n(m)
    {
    }
    ~A(){}
};
 
int main()
{
    A a(1);  //栈中分配
    A b = A(1);  //栈中分配
    A* c = new A(1);  //堆中分配
   delete c;
    return 0;
}

第一个隐式调用,第二个显式调用,两者都是在进程虚拟地址空间中的栈中分配内存,而第三种使用了new,在堆中分配了内存,栈中内存的分配和释放是由系统管理,堆中内存的分配和释放必须由程序员手动释放

总结

一般来说对于一个进程栈的大小远远小于堆的大小。
在Window下,栈的大小是2MB,Linux下,默认栈空间大小为8MB。对于堆,比如32位系统最大不超过2G,而64位系统最大不超过4G,当需要分配一个非常大的内存时,请用new
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在 堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就需要申请足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
由上可知,一般情况不使用new,直接使用类定义声明,申请内存特别大的情况下,或者作为函数返回值时,使用new创建对象

相关文章

  • C++内存

    认识C++内存 operator new, operator delete和new, delete operato...

  • new失败抛出异常吗?

    new/delete 在C++中动态分配与释放内存是通过new/delete和new []/delete []实现...

  • C++ 内存操作new & delete

    一、new & delete 回顾malloc/free, malloc申请而来的只是内存,严格地说并不是“对象”...

  • C++<第二十二篇>:new和delete运算符

    new 和 delete 是C++在C之后新增的两个运算符,new用来分类内存,delete用来释放内存。 (1)...

  • GC基础

    1.什么是垃圾 C语言申请内存:malloc free C++: new delete c/C++ 手动回收内存 ...

  • JVM笔记【1】-- 运行时数据区

    [TOC] (一)java内存区域管理 C/C++每一个new操作都需要自己去delete/free,而java里...

  • Boolan C++ 第五周 new和delete

    一、new和delete new和delete 是C++ 动态分配和释放内存的重要方式。当new一个对象时 先分配...

  • C++的new和delete详解

    new和delete的内部实现 C++中如果要在堆内存中创建和销毁对象需要借助关键字new和delete来完成。比...

  • c++_动态对象创建

    一.c语言 c语言使用malloc 来创建堆对象 二.c++ new操作符 delete操作符 如果new []...

  • C++ 复杂结构体的内存管理

    说明 C++ 中使用 new 和 delete 进行内存的申请和释放,二者成对出现。使用 new 申请的内存在堆中...

网友评论

      本文标题:C++ 内存操作new & delete

      本文链接:https://www.haomeiwen.com/subject/nzotqrtx.html