Non-Profit, International

Spirit unsterblich.

C++ new和delete

字数统计:742

C++设计了new运算符包装了内存分配和指针转换,delete运算符用于释放内存或者析构对象。新的语法使new和delete存在自己的使用技巧。

new operator是new运算符,new运算符的作用是调用operator new函数来进行内存分配。

对于内置类型和不含重载的类,编译器会通过重载的全局 operator newoperator new[] 函数(模板)来申请内存空间。如果有重载的new,则使用重载的版本(尽量不要重载全局的new)。

由于STL实际上包含多种重载的new,截止到目前(C++17-23),标准库一共重载了22种new:operator new, operator new[]

语法:

::(可选) new (布置参数)(可选) (类型) 初始化器(可选)

::(可选) new (布置参数)(可选) 类型 初始化器(可选)

最基本的new的重载版本有2个,简称为第一类new:


void* operator new  ( std::size_t count );
void* operator new[]( std::size_t count );

第一个版本用于分配单个对象,第二个版本用于分配多个对象。

值得注意的是,第二个版本实际上会带来额外开销:这个数组的首个4bit实际上会储存该数组的大小(称为overhead)。

第二类new是C++17开始使用内存对齐的new,其第二个参数是对齐的字节数,同样重载了两个版本。

这个版本由编译器进行调用,不需要传入对齐参数,在C++17开始为默认:/Zc:alignedNew (C++17 over-aligned allocation)

第三类new是不抛出异常的new,表示new分配失败时返回空指针。


void* operator new  ( std::size_t count, const std::nothrow_t& tag);
new(nothrow) int(10);

还有一类new称为布置(placement) new,其多了一个参数是分配的起始位置(指针)。

这类new不能重载,实际上是由编译器对两个版本的new进行再次重载的结果:


new(mem) int(10);

mem是一个指针,这个指针可以是堆上的也可以是栈上的。

使用new分配的内存需要使用delete进行释放,使用new[] 分配的内存需要使用delete[] 进行释放,由于overhead的存在,二者不能混用。

此外重载全局的new和delete实际上不会被调用,请使用成员函数。

参考

若无特殊声明,本人原创文章以 CC BY-SA 4.0许可协议 提供。