惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
H
Help Net Security
Jina AI
Jina AI
V
V2EX
G
Google Developers Blog
B
Blog
GbyAI
GbyAI
U
Unit 42
爱范儿
爱范儿
腾讯CDC
Engineering at Meta
Engineering at Meta
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
小众软件
小众软件
D
DataBreaches.Net
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
博客园 - 聂微东
The Cloudflare Blog
I
InfoQ
Microsoft Azure Blog
Microsoft Azure Blog
Hugging Face - Blog
Hugging Face - Blog
大猫的无限游戏
大猫的无限游戏

Victrid's Personal Site

斯普拉遁3打工模式联机网络过程分析 DHCP无类型静态路由──一个摆设 配置透明代理,实现无感上网 Generating Unlimited Grammar: A Messenger Perspective LaTeX插入其他PDF中的矢量图 光速不变原理和迈克尔孙──莫雷实验 交大葡萄演义 调试微信内置浏览器 欧悌甫戎篇 苏格拉底的申辩篇 LCA 最近公共祖先 弥罗斯人的辩论 埃斯库罗斯作品:波斯人、阿伽门农 电路理论资料 Coronavirus: A Humanitarian Crisis 雨夜 linux配置SSR 二叉堆的实现 懒政 Flipped: A Love Story 我宁可呆在这样的疯人院里 谈新发本地病例 勇敢与智慧 Powerful but Limited Drafted VLC Libva Error Troubleshooting Ring-Fit新上手 政治艺术化与艺术政治化 动态规划——从分割等和子集入手 被背叛的革命 (1)
Placement New
Victrid · 2020-04-01 · via Victrid's Personal Site

前几天写vector,可把我难倒了。最开始是一个测试用例,没有默认的构造函数,这个时候应该怎样去处理内存的分配。

我想到,既然一个元素的大小,即sizeof()是固定的,我们就可以先申请这个空间,等到需要使用的时候再赋值。

memcpy() 失败

虽然只学过C++化的简化版C语言,但我想到了malloc()方法,这就是一个只申请空间,不去填充空间的方法。

这对于传统的数据,就是说所谓的POD(Plain Old Data)是很好的。我的整个实现逻辑也是memcpy(),这样的处理速度快的多。

但是不是POD的类,占用了堆来存储部分内容,在他的存储空间里只存储了指向堆的指针。所以memcpy()只执行了浅拷贝,拷贝的实际上是指针,它指向的堆内存储是不变的。当原对象析构释放堆的时候,拷贝对象就被破坏了;被覆盖的对象没有进行析构而是直接被覆盖,内部申请的堆内存就被泄漏。

同样,当被覆盖的地方原本不存在对象,即只分配了内存却没有初始化内存空间时,如果直接调用类的赋值,这个赋值方法是不能检测原来的对象是否正确的。一旦有针对原指向堆内存的指针,现在是随机指针进行的操作,例如直接向动态数组发起memcpy(),就会出现段错误,或者内存的错误覆盖。

所以,凯撒的归凯撒,经过查阅资料,我找到了下面两个C++的处理方法。

为什么我最开始不用new呢?因为new在调用的时候会自动调用构造函数,而一个用例没有默认构造函数,new就会出错。

怎么解决呢?经过资料的学习,我找到了placement new这个用法。实际上,new和delete是通过以下的过程实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
A* p=new A;					B* t=new B[_NUM];
delete p; delete [] t;



operator new(sizeof(A)); operator new[](_NUM*sizeof(B));


new(p) A(); for(size_t in=0;in<_NUM;in++)
new(t+in*sizeof(B)) B();



p->~A(); for(size_t in=0;in<_NUM;in++)
(t+in*sizeof(T))->~B();

operator delete p; operator delete [] t;

过程中的placement new实际上就是按需调用构造函数,而operator new/delete则是只申请内存而不初始化,和malloc/free功能是一致的。好像构造函数是不能够显式调用的,所以placement new来解决这个问题。

Author: Victrid

Permanent Link: https://victrid.dev/2020/nt-new/

License: Copyright (c) 2025 victrid Terms of Use

Ads by Google

Read our privacy policy on how these personalized advertisements are delivered to you.

For your reading experience, we provide full-text RSS feeds. Although math formulas cannot be displayed well, the interface can be adjusted as you like and there are no ads.