前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >placement new

placement new

作者头像
JIFF
发布2019-08-02 15:24:25
1K0
发布2019-08-02 15:24:25
举报
文章被收录于专栏:Toddler的笔记Toddler的笔记

C++11 中,形如 new(buffer)T; 的语句即为 placement new 语法

如何让一个已经 contructed 的 object 重新调用其 constructor?placement new 就是答案。

placement new 可以指定 "new/新建" 的内存的具体位置。

  • there's no "placement delete". with placement new, you could "new" memory in stack/heap/static/thread_local storage area.
  • there's no book keeping area for placement new. The "allocated" size is exactly the same with the size of the object which was newed.
    • (注意"new/新建/allocated"是引号,因为实际上并没有新的内存被 alloc)
  • placement new 出来的 object,"销毁"时不会自动调用其 destructor,如果需要的话,可以手动调用它
    • (为什么"销毁"是引号?难以言喻,读完本篇应该可以意会)

首先补充一点:一般来说,C++ 有四种 storage categories

  • static storage duration: 即 global 和 staic local
  • thread_local storage duration: C++11 new keyword. 与线程同生同死
  • dynamic storage duration: 即存在于 Heap,例如在 Linux x64 中地址从小到大增长
  • automatic storage duration: 即存在于 Stack,例如 function frame
  • 第五种 register 在 C++ 中俨然已如空气,一般编译器都会直接忽略它。

举一个 auto/thread_local/static 的例子:

代码语言:javascript
复制
struct T {
    int val;
    T(int v) : val(v) {}
    T(int a, int b) : val(a + b) {}
    ~T() {
        cout << "val: " << val << endl;
    }
};
{
    // static char .. | thread_local char ..
    char buffer[16];
    T* ptr = new (buffer) T(10);

    // 此时 ptr->val == 10, ptr的值 == buffer的首地址
    cout << ptr->val;
}
// 离开 scope,对于 auto 类型的 char buffer[10],其内存被回收。
// ptr->~T() 不会被调用。注意是 stack 中的 buffer 数组的析构函数被调用。
// 当然对于 buffer 这样的 POD 并没有析构函数
//
// 如果 buffer 是 thread_local,则当 thread 结束并被join 或者 detach 后,
// buffer 的内存被回收。
//
// 如果 buffer 是 static,则当 process exit 时,process 所有的内存被操作系统回收,
// 当然也包括 buffer。

再举一个例子:

代码语言:javascript
复制
{
    // class T constructor T(int);
    T t(1);
    T* ptr = &t;

    // 这里调用它只是为了打印。实际使用中析构函数会释放一些资源,
    // 对应构造函数会创建一些资源。
    ptr->~T();

    // class T constructor T(int, int);
    new (ptr) T(2, 3);
}
// t 的生命结束时,t.~T() 再次被调用

再举一个 heap 的例子:

代码语言:javascript
复制
{
    // 申请 sizeof(T) 的内存 + 一定数量的 book keeping 内存
    T* ptr = new T(1);

    // T(1)的内存被直接覆盖了,注意其 destructor 没有被调用
    T* ptr2 = new (ptr) T(2, 3);

    // ptr->~T() 被调用。一共有:一次底层 malloc,两次 ctor,
    // 一次 dtor,一次底层 free 被调用。
    // 同时 delete()库函数 会 free book keeping area
    delete ptr;
}
本文参与?腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-06,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 Toddler的笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体同步曝光计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++11 中,形如 new(buffer)T; 的语句即为 placement new 语法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com