共计 3494 个字符,预计需要花费 9 分钟才能阅读完成。
- 自在存储区和堆
-
placement-new、new operator、operator new
- 区别
- demo1:operator new/operator delete 应用
- new 与 malloc
自在存储区和堆
- 参考:https://stackoverflow.com/que…
- 参考:https://www.quora.com/What-is…
- 参考:https://www.cnblogs.com/qg-wh…
- 参考:https://blog.csdn.net/nie1994…
-
两种动态内存区域。
- heap
-
free store
C++ 的内存布局
- 堆(
malloc/free
)、栈、自在存储区(new delete
)、全局 / 动态存储区、常量存储区
free store 和 heap 的区别(语言背景角度)
-
malloc
在堆上调配的内存块,应用free
开释内存,而new
所申请的内存则是在自在存储区上,应用delete
来开释- 精确来说 free store 对应的是
operator new
- 精确来说 free store 对应的是
- free store 和 headp 是不同内存区域吗(操作系统角度)
多角度探讨异同
- (编译器上)大部分 C ++ 编译器 默认应用堆来实现自在存储。也就是说这个时候说它是在堆上还是在自在存储区上都对。
-
(语言背景)堆是 C 或操作系统概念。自在存储区是 C ++ 形象进去的逻辑概念。
- C++ 提出该概念更加强调了这两种内存自在调配不应该被互操作,且 C ++ 使得内存自在调配更加灵便(placement-new)。
- C++ 中应用 malloc 和 free 在技术上是可能的(偶然有用),但这种 做法应该防止或至多是孤立的。
-
(程序角度)
- free store:对象的生命周期 能够小于 调配存储空间的工夫(即 free store 能够在不立刻初始化的状况下分配内存,并且能够再不立刻开释内存的状况下销毁对象)
-
heap:尽管默认的全局 new 和 delete(注:特指
::operator new
)可能由特定编译器依据 malloc 和 free 实现,但堆与闲暇存储不同,并且在一个区域(heap or free store)中调配的内存不能在另一个区域中平安地开释。- 从堆 (malloc 进去的) 中的内存能够用
placement-new
结构和 显式析构 ,这样的话对于free store 对象生存期的阐明再这里也实用。
- 从堆 (malloc 进去的) 中的内存能够用
placement-new、new operator、operator new
- 参考:https://blog.51cto.com/yiluoh…
- * 参考:https://www.cnblogs.com/luxia…
区别
new operator/delete operator
就是new
和delete
操作符 ,而operator new/operator delete
是函数。(注:不是很精确,然而很帮忙了解)-
new operator
(操作符)- 作用:调配足够的空间(调用
operator new
),并且调用对象的构造函数 -
执行过程:
- 调用 operator new 分配内存
- 调用构造函数生成类对象
- 返回相应指针
- 重载:不能够被重载
- new operator 与 delete operator 的行为是不可能也不应该被扭转,这是 C ++ 规范作出的承诺
- 作用:调配足够的空间(调用
-
operator new
(函数)- 作用:分配内存,但不执行结构
-
重载:能够重载。
- 返回类型必须申明为
void*
- 第一个参数类型必须为表白要求调配空间的大小(字节),类型为
size_t
- 能够带其它参数
- 返回类型必须申明为
- 特例:
placement new
就是`operator new
的重载。不分配内存,而是利用已有内存 - 全局:
::operator new
,通用操作,在 heap 中调配 - operator new 与 operator delete 和 C 语言中的 malloc 与 free 对应,只负责调配及开释空间,然而不可能穿插应用,因为一个对象是 free store 另一个是 heap。
-
placement-new
- 作用:容许用户把一个对象放到一个特定的中央,达到调用构造函数的成果
-
重载:
placement new
是重载operator new
的一个规范、全局的版本,它不可能被自定义的版本代替.(不像一般版本的operator new
和operator delete
可能被替换)- 也就是不能重载笼罩
- 签名:
void *operator new(size_t, void * p) throw() { return p;}
placement-new
执行时,疏忽了 size_t,该参数没有作用。只应用和返回void* p
。-
应用场景:
- buffer 性能进步:间接 new 一个数组当缓冲区,会调用构造函数,影响性能。能够先预调配一块内存,之后用 placement-new 结构
- 节俭了堆中找足够大的空间 的工夫。
placement-new
的内存调配是常数工夫,因为曾经调配好了。
-
辨别一般 new:
Widget * p = new Widget; //ordinary new
pi = new (ptr) int; pi = new (ptr) int; //placement new
为什么有必要写本人的 operator new 和 operator delete?
- 效率。具体看《Effective C++》中的第二章内存治理
Placement new 应用步骤
-
步骤 1:调配缓存空间,有三种形式
-
堆中获取
char * buff = new [N*sizeof(Task)]; // 分配内存
-
栈上获取
char buf[N*sizeof(Task)]; // 分配内存
-
间接用地址。(地址必须有有意义)
void* buf = reinterpret_cast<void*> (0xF00F);
-
-
步骤 2:对象的结构
Task *ptask = new (buf) Task
-
步骤 3:应用
ptask->memberfunction();
-
步骤 4:对象的析构
ptask->~Task();
- 必须显示调用析构
-
步骤 5:开释缓存空间
- 能够重复利用缓存并给它调配一个新的对象(反复步骤 2,3,4)
delete [] buf;
- 如果你的确须要应用 placement new,请认真遵循以上的步骤。
demo1:operator new/operator delete 应用
#include <iostream>
#include <string>
using namespace std;
class X
{
public:
X() { cout<<"constructor of X"<<endl;}
~X() { cout<<"destructor of X"<<endl;}
void* operator new(size_t size,string str)
{
cout<<"operator new size"<<size<<"with string"<<str<<endl;
return ::operator new(size);
}
void operator delete(void* pointee)
{
cout<<"operator delete"<<endl;
::operator delete(pointee);
}
private:
int num; // 4 字节
};
int main()
{
// 调用 new 操作符(留神不是 operator new), 这里须要传入 行将调用 operator new 所需的第二个参数,size 参数 new 操作符会本人给
X *px = new("A new class") X;
delete px;
return 0;
}
operator new size 4 with string A new class
constructor of X
destructor of X
operator delete
-
后果解析
X *px = new("A new class") X;
中,调用的是 new 操作符(留神不是 operator new), 这里须要传入 行将调用 operator new 所需的第二个参数,size 参数 new 操作符会本人给delete px;
(为delete operator
)时,先调用析构函数,再调用operator delete
new 与 malloc
- https://www.cnblogs.com/qg-wh…
特色 | new/delete | malloc/free |
---|---|---|
分配内存的地位 | 自在存储区 | 堆 |
内存调配胜利的返回值 | 残缺类型指针 | void* |
内存调配失败的返回值 | 默认抛出异样 | 返回 NULL |
分配内存的大小 | 由编译器依据类型计算得出 | 必须显式指定字节数 |
解决数组 | 有解决数组的 new 版本 new[] | 须要用户计算数组的大小后进行内存调配 |
已分配内存的裁减 | 无奈直观地解决 | 应用 realloc 简略实现 |
是否互相调用 | 能够,看具体的 operator new/delete 实现 | 不可调用 new |
分配内存时内存不足 | 客户可能指定处理函数或重新制定分配器 | 无奈通过用户代码进行解决 |
函数重载 | 容许 | 不容许 |
构造函数与析构函数 | 调用 | 不调用 |
正文完