C++ new 和 malloc 的区别?

这篇具有很好参考价值的文章主要介绍了C++ new 和 malloc 的区别?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 C++ new 和 malloc 的区别?,#C++基础,c++,开发语言,设计模式

相关系列文章

C++ new 和 malloc 的区别?

C++内存分配策略​​​​​​​

目录

1.引言

2.区别

2.1.申请的内存分配区域

2.2.类型安全和自动大小计算

2.3.构造函数和析构函数的调用

2.4.异常处理

2.5.配对简便性

2.6.new 的重载

2.7.关键字和操作符

3.总结


1.引言

new 和 delete 在 C++ 中被引入,主要是为了解决 malloc 和 free 在 C 语言中的一些限制和问题,特别是在面向对象编程方面。以下是 new/delete 相比于 malloc/free 的主要区别。

2.区别

2.1.申请的内存分配区域

        new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。

        那么自由存储区是否能够是堆(问题等价于new是否能在堆上动态分配内存),这取决于operator new 的实现细节。自由存储区不仅可以是堆,还可以是静态存储区,这都看operator new在哪里为对象分配内存。

        特别的,new甚至可以不为对象分配内存!定位new的功能可以办到这一点:

new (place_address) type

        place_address为一个指针,代表一块内存的地址。当使用上面这种仅以一个地址调用new操作符时,new操作符调用特殊的operator new,也就是下面这个版本:

void * operator new (size_t,void *) 
//不允许重定义这个版本的operator new

        这个operator new不分配任何的内存,它只是简单地返回指针实参,然后右new表达式负责在place_address指定的地址进行对象的初始化工作。

2.2.类型安全和自动大小计算

malloc/free 示例:

#include <stdlib.h>

struct MyStruct {
    int data;
    // ... 其他成员 ...
};

int main() {
    // 使用 malloc 分配内存,需要手动计算大小
    MyStruct* p = (MyStruct*)malloc(sizeof(MyStruct));
    p->data = 10;
    free(p);
    return 0;
}

new/delete 示例:

struct MyStruct {
    int data;
    // ... 其他成员 ...
};

int main() {
    // 使用 new 分配内存,自动处理大小和类型
    MyStruct* p = new MyStruct;
    p->data = 10;
    delete p;
    return 0;
}

区别:

  • new 自动计算所需内存的大小,而 malloc 需要程序员手动计算。

  • new 提供类型安全,返回正确类型的指针,避免了强制类型转换的需要。

2.3.构造函数和析构函数的调用

使用new操作符来分配对象内存时会经历三个步骤:
        1)调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。
        2)编译器运行相应的构造函数以构造对象,并为其传入初值。
        3)对象构造完成后,返回一个指向该对象的指针。
 使用delete操作符来释放对象内存时会经历两个步骤:
        1)调用对象的析构函数。
        2)编译器调用operator delete(或operator delete[])函数释放内存空间。
        总之来说,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会。下面看个示例:

class MyClass {
public:
    MyClass() { std::cout << "Constructor called\n"; }
    ~MyClass() { std::cout << "Destructor called\n"; }
};

int main() {
    MyClass* obj = new MyClass; // 调用构造函数
    delete obj;                 // 调用析构函数
    return 0;
}

区别:

  • new 在分配内存时调用对象的构造函数,delete 在释放内存时调用析构函数。

  • malloc 和 free 只处理内存分配和释放,不调用构造函数和析构函数。

2.4.异常处理

        new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。示例如下:

int main() {
    try {
        int* p = new int[10000000000]; // 尝试分配大量内存
    } catch (const std::bad_alloc& e) {
        std::cerr << "Memory allocation failed: " << e.what() << '\n';
    }
    return 0;
}

区别:

  • new 在内存分配失败时抛出异常(如 std::bad_alloc),而 malloc 在失败时返回 NULL

  • 这使得 new 能够更好地集成到 C++ 的异常处理框架中。

2.5.配对简便性

  • new 和 delete 是为对象配对的,而 malloc 和 free 需要显式计算大小。

如:

//[1]
A * ptr = new A[10];//分配10个A对象
delete []ptr;

//[2]
int * ptr = (int *) malloc( sizeof(int)* 10 );
//分配一个10个int元素的数组
free(ptr);
  • new[] 和 delete[] 用于数组,简化了数组内存管理。

new对数组的支持体现在它会分别调用构造函数函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。注意delete[]要与new[]配套使用,不然会找出数组对象部分释放的现象,造成内存泄漏

2.6.new 的重载

是的,C++ 允许重载 new 操作符。这意味着你可以定义自己的 new 操作符来改变对象的分配方式。重载 new 可以用于自定义内存管理,追踪内存分配,或者引入特殊的内存分配策略。标准库是定义了operator new函数和operator delete函数的8个重载版本:

//这些版本可能抛出异常
void * operator new(size_t);
void * operator new[](size_t);
void * operator delete (void * )noexcept;
void * operator delete[](void *0)noexcept;
//这些版本承诺不抛出异常
void * operator new(size_t ,nothrow_t&) noexcept;
void * operator new[](size_t, nothrow_t& );
void * operator delete (void *,nothrow_t& )noexcept;
void * operator delete[](void *0,nothrow_t& )noexcept;

         我们可以自定义上面函数版本中的任意一个,前提是自定义版本必须位于全局作用域或者类作用域中。

        重载 new 需要提供与系统 new 相同的返回类型和参数列表。最常见的形式是重载全局 new 和 delete

void* operator new(std::size_t size) {
    std::cout << "Custom new for size " << size << std::endl;
    return std::malloc(size);
}

void operator delete(void* memory) {
    std::cout << "Custom delete" << std::endl;
    std::free(memory);
}

类也可以重载其自身的 new 和 delete,这对于控制特定类的对象分配非常有用。

class MyClass {
public:
    void* operator new(std::size_t size) {
        std::cout << "MyClass new" << std::endl;
        return std::malloc(size);
    }

    void operator delete(void* memory) {
        std::cout << "MyClass delete" << std::endl;
        std::free(memory);
    }
};

2.7.关键字和操作符

new 是操作符,malloc 是函数。

关键字(Keywords)和操作符(Operators)在编程语言中是两个不同的概念:

  • 关键字:这些是编程语言预定义的保留字,每个关键字有特定的含义,并在语言的语法中扮演特定的角色。例如,ifwhilereturn 等在 C++ 中都是关键字。关键字不能用作变量名或函数名。

  • 操作符:操作符用于执行操作,如算术运算、逻辑运算、比较等。在 C++ 中,一些操作符可以被重载,这意味着你可以改变它们的行为以适应特定类型的操作。例如,+-*/new 等都是操作符。

有些情况下,某些关键字也可以被视为操作符。例如,new 和 delete 在 C++ 中既是关键字也是操作符。它们作为关键字,表示特定的动作(分配和释放内存),同时它们的行为可以像操作符那样被重载。

3.总结

new/delete 提供了更符合 C++ 面向对象特性的内存管理方式。它们处理类型安全、对象生命周期(构造和析构)、异常安全以及简化语法。然而,这些改进也带来了一定的性能开销,这在某些性能敏感的应用中可能是一个考虑因素。在 C++ 中,new/delete 是推荐的方式,因为它们提供了更安全和便利的内存管理机制。

C++内存分配策略-CSDN博客文章来源地址https://www.toymoban.com/news/detail-825987.html

到了这里,关于C++ new 和 malloc 的区别?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • malloc 和 new

    malloc(c)与new(c++)都是分配空间的函数 new一个对象ha~ ha~ 定义 malloc动态内存分配函数,用于申请一块连续的指定大小的内存块区域以void 类型返回分配的内存区域地址。 s malloc函数是一种分配长度为num_bytes字节的内存块的函数,可以向系统申请分配指定size个字节的内存空

    2024年02月11日
    浏览(30)
  • C++的new与JAVA中new的区别

    ·C++的 new 和Java的 new 在语义上有一些区别,下面是它们之间的区别: 内存管理: C++中的 new 用于动态分配内存,并返回指向该内存的指针。需要手动使用 delete 释放内存,否则会导致内存泄漏。 Java中的 new 同样用于动态分配内存,但是垃圾回收器负责自动释放

    2024年02月11日
    浏览(27)
  • 【C++】——C++基础知识点(C++和C语言的区别)

    C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式 等。熟悉C语言之后,对C++学习有一定的帮助。 本博客目标: 1.补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的,比如:作用域方面、IO方面、函数方面、指

    2024年02月03日
    浏览(37)
  • C++内存分配揭秘:new操作符::operator new和Placement new的区别

      在 C++ 中, new  操作符、 ::operator new  和 placement new 是用于动态内存分配的工具,但它们有不同的用法和行为。以下是它们的区别和用法的详细实例: new  操作符用于在堆上动态分配内存,并调用对象的构造函数初始化对象。 ::operator new  是 C++ 中的全局函数,用于分配内

    2024年01月18日
    浏览(29)
  • 从C语言到C++_37(特殊类设计和C++类型转换)单例模式

    目录 1. 特殊类设计 1.1 不能被拷贝的类 1.2 只能在堆上创建的类 1.3 只能在栈上创建的类 1.4 不能被继承的类 1.5 只能创建一个对象的类(单例模式)(重点) 1.5.1 饿汉模式 1.5.2 懒汉模式 2. 类型转换 2.1 static_cast 2.2 reinterpret_cast 2.3 const_cast 2.4 dynamic_cast 3. RTTI(了解)和类型转换常见面

    2024年02月10日
    浏览(34)
  • 【C++基础(九)】C++内存管理--new一个对象出来

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C++从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C++   🔝🔝 在C语言中,有四个内存管理函数: malloc,calloc,realloc和free 但是它们的使用十分的不方便: 代码量很大,并且有一个新的问题: malloc函数不会初始

    2024年02月14日
    浏览(46)
  • 工厂模式和设计模式的区别是什么?

    工厂模式和设计模式是两个不同的概念。 1.工厂模式(Factory Pattern)是一种创建型设计模式,旨在通过工厂类来创建对象,而不是直接在代码中实例化对象。工厂模式将对象的创建与使用分离,客户端只需要通过工厂类来获取所需的对象,而无需了解对象的具体创建过程。工厂

    2024年02月12日
    浏览(30)
  • 设计模式:简单工厂、工厂方法、抽象工厂的区别

    描述: 简单工厂模式并不是严格意义上的设计模式,而更像是一种编程习惯或者说是一种创建对象的简单方式。它使用一个工厂类来创建对象,这个工厂类包含一个方法,根据输入的参数或条件来创建相应的对象实例。 举例: 描述: 工厂方法模式是一种创建型模式,它定义

    2024年01月21日
    浏览(37)
  • 【设计模式】适配器和桥接器模式有什么区别?

    今天我探讨一下适配器模式和桥接模式,这两种模式往往容易被混淆,我们希望通过比较他们的区别和联系,能够让大家有更清晰的认识。 适配器模式:连接不兼容接口 当你有一个类的接口不兼容你的系统,而你又不希望修改这个类的源代码时,适配器模式就能派上用场。

    2024年01月25日
    浏览(34)
  • calloc、malloc、realloc函数的区别及用法

    三者都是分配内存,都是stdlib.h库里的函数,但是也存在一些差异。 (1)malloc函数。其原型void *malloc(unsigned int num_bytes); num_byte为要申请的空间大小,需要我们手动的去计算,如int *p = (int )malloc(20 sizeof(int)),如果编译器默认int为4字节存储的话,那么计算结果是80Byte,一次申请

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包