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

    文章

    176

    浏览量

    25296
  • C++语言
    +关注

    关注

    0

    文章

    146

    浏览量

    6878
收藏 人收藏

    评论

    相关推荐

    深入C++内存管理

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

    SystemVerilog中的类构造函数new

    在systemverilog中,如果一个类没有显式地声明构造函数(new()),那么编译仿真工具会自动提供一个隐式的new()函数。这个new函数会默认地将所有属性变量。
    发表于 11-16 09:58 2812次阅读

    MDK5.23将C/C++的字体由系统默认的Courier New切换为Consolas字体,再切换回去Courier New字体选项不见了?

    MDK5.23,将C/C++的字体由系统默认的Courier New切换为Consolas字体,想再切换回去的时候,发现Courier New字体选项居然不见了??百思不得其解,这难道
    发表于 04-23 07:09

    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 909次阅读
    A <b class='flag-5'>New</b> Standard for Multiproces

    Safetosleep安宝睡智能床垫NEW

    Safetosleep安宝睡智能床垫NEW
    发表于 01-04 15:56 0次下载

    placement new详解

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

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

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

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

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

    [TEST] [NEW] ユーザーズマニュアル  ハードウェア編

    [TEST] [NEW] ユーザーズマニュアル  ハードウェア編
    发表于 03-17 19:45 0次下载
    [TEST]  [<b class='flag-5'>NEW</b>] ユーザーズマニュアル  ハードウェア編

    UVM中类的例化用new还是create

    UVM中类的例化用new和create有什么不同?什么时候可以用new?什么时候该用create? new是OOP自带属性,create是UVM override属性,可以理解成create比
    的头像 发表于 03-21 11:26 722次阅读

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

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

    [TEST] [NEW] ユーザーズマニュアル  ハードウェア編

    [TEST] [NEW] ユーザーズマニュアル  ハードウェア編
    发表于 07-07 18:36 0次下载
    [TEST]  [<b class='flag-5'>NEW</b>] ユーザーズマニュアル  ハードウェア編

    new和malloc的区别

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