0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++内存管理operator new和placement new

冬至子 来源:鸣鸣锣的小屋 作者:Maxwell Luo 2023-07-22 09:58 次阅读

>>> 背景

最近在看一些C++资料的过程中,说到在初始化列表中使用关键字new来分配新内存不是异常安全的,应该使用运算符new。这里就引发了我对C++ new的全新认识。

class A {
public:
    A(int a) : px(new int(a)) {}  // 当然这里基础类是不会异常的
    int* px;
};

>>> 内容

首先我们来回忆一下最常规的new用法。首先创建一个测试类A,并在其构造和析构函数里面打印提示语句。可以发现,在new一个A对象的时候调用了构造函数,在delete一个A对象的时候析构了此对象。而且与C标准库中的malloc函数相比,new关键字不需要知道分配的字节数,而是对类型大小做了自动推断,显然更加方便。

class A {
public:
    A(int a) : _a(a) {
        cout < < "object A(" < < _a < < ") is constructed.n";
    }
    ~A() {
        cout < < "object A(" < < _a < < ") is destructed.n";
    }
    int _a;
};


int main() {
    A* obj = new A(1);
    delete obj;


    return 0;
}
object A(1) is constructed.
object A(1) is destructed.

但是方便的代价就是隐藏了很多细节,从而可能导致使用者在没有充分理解的情况下造成误用。其实关键字new做了非常多的操作。

这里首先给出3个概念,分别是:关键字new、操作符new和放置new(或者说,keywords new、operator new、placement new)。它们之间的关系大概如下所示。

图片

当我们使用关键字new去创建一个对象时,会首先根据A类型推断出需要申请的内存字节数,然后再交给operator new去按字节数申请一块可用的内存(否则抛出异常),最后调用类的构造函数创造一个对象保存在申请的这段内存中。

图片

而placement new起到的作用是在分配好的内存上创建对象,和operator new有那么一点互补的意思。placement new的引入是为了避免一些频繁的内存申请和回收操作,可以专门申请一块内存做重复的计算,而不是需要一个对象就申请一个内存,从而提高效率。

图片

下面是一个比较综合的例子,来表现这些new之间不同。可以看到,我们首先通过operator new来创建一块能够容纳3个A对象的内存空间,然后通过placement new来在这个申请好的内存空间上创建对象,最后使用operator delete把申请的空间销毁。

可以看到operator new不会调用构造函数,operator delete也不会调用析构函数。通过placement new配合起始指针的偏移,可以逐个在新内存上创建有意义的数据对象。

int main() {
    A* mempool = (A*)operator new(sizeof(A) * 3);
    cout < < "Memory is allocated!n";
    A* obj1 = new(mempool) A(1);
    A* obj2 = new(mempool + 1) A(2);
    A* obj3 = new(mempool + 2) A(3);
    cout < < obj1- >_a < < endl;
    cout < < obj2- >_a < < endl;
    cout < < obj3- >_a < < endl;
    operator delete(mempool);
    cout < < obj1- >_a < < endl;
    cout < < obj2- >_a < < endl;
    cout < < obj3- >_a < < endl;


    return 0;
}
Memory is allocated!
object A(1) is constructed.
object A(2) is constructed.
object A(3) is constructed.
1
2
3
35134640
0
1448320

>>> 小结

可以看出,C++在内存分配引入了不少的概念,operator new和operator delete都是可以被自定义类重载的,这就给予了程序员很好的自由度。除了使用new和delete来管理内存外,C++还引入了更为复杂的allocator(或分配器)的概念。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 分配器
    +关注

    关注

    0

    文章

    193

    浏览量

    25690
  • C++语言
    +关注

    关注

    0

    文章

    147

    浏览量

    6949
收藏 人收藏

    评论

    相关推荐

    深入C++内存管理

    说到 C++内存管理,我们可能会想到栈空间的本地变量、堆上通过 new 动态分配的变量以及全局命名空间的变量等,这些变量的分配位置都是由系统来控制
    发表于 11-12 09:29 598次阅读

    New C++基础与提高

    New C++基础与提高-王桂林
    发表于 09-22 15:44

    请问C++new和不用new创建类对象区别是什么?

    起初刚学C++时,很不习惯用new,后来看老外的程序,发现几乎都是使用new,想一想区别也不是太大,但是在大一点的项目设计中,有时候不使用new的确会带来很多问题。当然这都是跟
    发表于 11-05 07:27

    A New Standard for Multiproces

    A New Stan
    发表于 09-15 10:06 1044次阅读
    A <b class='flag-5'>New</b> Standard for Multiproces

    placement new详解

    placement new是重载operator new的一个标准、全局的版本,它不能被自定义的版本代替(不像普通的operator
    发表于 03-02 14:24 0次下载

    C++语法的外围基础

    程序对内存空间的动态分配的频繁程度要求简化语言的相关语法的格式。C++语法规定new算符等效于C语言中mal1oc一类的函数功能;free算符等效于
    发表于 03-15 16:55 10次下载

    了解一下比较复杂也非常神秘的new

    new”是C++的一个关键字,同时也是操作符。关于new的话题非常多,因为它确实比较复杂,也非常神秘。
    的头像 发表于 04-23 15:27 3582次阅读
    了解一下比较复杂也非常神秘的<b class='flag-5'>new</b>

    新英特尔C/C++编译器16.0中C/C++语言的特点

    This talk will cover new features in Intel® C/C++ Compiler 16.0 as part of the Intel® Parallel
    的头像 发表于 10-23 06:57 4190次阅读

    C++内存管理技术的详细资料说明

    内存管理C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,
    发表于 03-14 08:00 4次下载

    C++内存管理详细介绍

    引言 说到 C++内存管理,我们可能会想到栈空间的本地变量、堆上通过 new 动态分配的变量以及全局命名空间的变量等,这些变量的分配位置都是由系统来控制
    的头像 发表于 01-11 10:31 2679次阅读

    如何让new操作符不分配内存,只构造

    placement new 就可以解决这个问题。我们构造对象都是在一个预先准备好了的内存缓冲区中进行,不需要查找内存内存分配的时间是常数;
    的头像 发表于 01-19 17:01 1965次阅读

    new和malloc函数详细分析底层逻辑

    new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new
    的头像 发表于 04-03 09:29 669次阅读

    嵌入式C++内存管理的应用程序

    说到 C++内存管理,我们可能会想到栈空间的本地变量、堆上通过 new 动态分配的变量以及全局命名空间的变量等,这些变量的分配位置都是由系统来控制
    发表于 10-12 10:37 291次阅读
    嵌入式<b class='flag-5'>C++</b><b class='flag-5'>内存</b><b class='flag-5'>管理</b>的应用程序

    new和malloc的区别

    1. 申请的内存所在位置 new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是
    的头像 发表于 11-11 11:29 529次阅读
    <b class='flag-5'>new</b>和malloc的区别

    C++内存管理问题

    写服务端的,内存是一个绕不过的问题,而用C++写的,这个问题就显得更严重。进程的内存持续上涨,有可能是正常的内存占用,也有可能是内存碎片,而
    的头像 发表于 11-13 11:13 595次阅读
    <b class='flag-5'>C++</b><b class='flag-5'>内存</b><b class='flag-5'>管理</b>问题