new的六种重载形式

本文详细介绍了C++中new操作符的六种重载形式及其用途,包括简单的对象创建、动态对象数组创建、带参数的new操作符、placement new等,并解释了如何通过重载operator new来自定义内存分配策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当写出
p = new P();
这样的代码的时候, 实际上有两步操作, 首先分配内存,
然后在分配好的内存之上初始化类成员.

第二步是有构造函数完成的, 第一步就是new函数的工作.

全局的new有六种重载形式,
void *operator new(std::size_t count)
    throw(std::bad_alloc);             //一般的版本

void *operator new(std::size_t count,  //兼容早版本的new
    const std::nothrow_t&) throw();    //内存分配失败不会抛出异常

void *operator new(std::size_t count, void *ptr) throw();
                                       //placement版本
void *operator new[](std::size_t count)  //
    throw(std::bad_alloc);

void *operator new[](std::size_t count,  //
    const std::nothrow_t&) throw();

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

所以, 刚才的用法, 就是使用new函数的一种重载形式.
如果A这个对象以同样实行重载了new函数的化, 作为成员函数
会被优先调用.
 
C++的各种new简介

1.new T

第一种new最简单,调用类的(如果重载了的话)或者全局的operator new分配空间,然后用
类型后面列的参数来调用构造函数,用法是
new TypeName(initial_args_list). 如果没有参数,括号一般可以省略.例如

int *p=new int;
int *p=new int(10);
int *p=new foo("hello");

通过调用delete来销毁:
delete p;

2. new T[]
这种new用来创建一个动态的对象数组,他会调用对象的operator new[]来分配内存(如果
没有则调用operator new,搜索顺序同上),然后调用对象的默认构造函数初始化每个对象
用法:
new TypeName[num_of_objects];
例如
int *p= new int[10];
销毁时使用operator delete[]

3.new()T 和new() T[]
这是个带参数的new,这种形式的new会调用operator new(size_t,OtherType)来分配内存
这里的OtherType要和new括号里的参数的类型兼容,

这种语法通常用来在某个特定的地址构件对象,称为placement new,前提是operator new
(size_t,void*)已经定义,通常编译器已经提供了一个实现,包含<new>头文件即可,这个
实现只是简单的把参数的指定的地址返回,因而new()运算符就会在括号里的地址上创建
对象

需要说明的是,第二个参数不是一定要是void*,可以识别的合法类型,这时候由C++的重载
机制来决定调用那个operator new

当然,我们可以提供自己的operator new(size_,Type),来决定new的行为,比如
char data[1000][sizeof(foo)];
inline void* operator new(size_t ,int n)
{
        return data[n];
}

就可以使用这样有趣的语法来创建对象:
foo *p=new(6) foo(); //把对象创建在data的第六个单元上
的确很有意思
标准库还提供了一个nothrow的实现:
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();

就可以实现调用new失败时不抛出异常
new(nothrow) int(10);
// nothrow 是std::nothrow_t的一个实例


placement new 创建的对象不能直接delete来销毁,而是要调用对象的析够函数来销毁对
象,至于对象所占的内存如何处理,要看这块内存的具体来源

4. operator new(size_t)
这个的运算符分配参数指定大小的内存并返回首地址,可以为自定义的类重载这个运算符,
方法就是在类里面声明加上
void *operator new(size_t size)
{
        //在这里分配内存并返回其地址
}
无论是否声明,类里面重载的各种operator new和operator delete都是具有static属性的

一般不需要直接调用operator new,除非直接分配原始内存(这一点类似于C的malloc)
在冲突的情况下要调用全局的operator加上::作用域运算符:
::operator new(1000); // 分配1000个字节

返回的内存需要回收的话,调用对应的operator delete

5.operator new[](size_t)

这个也是分配内存,,只不过是专门针对数组,也就是new T[]这种形式,当然,需要时可以
显式调用

6.operator new(size_t size, OtherType other_value)
和operator new[](size_t size, OtherType other_value)
参见上面的new()


需要强调的是,new用来创建对象并分配内存,它的行为是不可改变的,可以改变的是各种
operator new,我们就可以通过重载operator new来实现我们的内存分配方案.

 

在C++中,可以重载newdelete运算符以定制动态内存管理的行为。重载new运算符可以用于自定义内存分配的方式,而重载delete运算符可以用于自定义内存释放的方式。 重载new运算符的一种常见方式是定义一个全局的new运算符函数,并使用该函数来执行内存分配。例如: ```cpp void* operator new(size_t size) { // 自定义内存分配逻辑 void* ptr = malloc(size); // 检查分配是否成功 if (ptr == nullptr) { throw std::bad_alloc(); } return ptr; } ``` 重载delete运算符的一种常见方式是定义一个全局的delete运算符函数,并使用该函数来执行内存释放。例如: ```cpp void operator delete(void* ptr) noexcept { // 自定义内存释放逻辑 free(ptr); } ``` 需要注意的是,如果重载new运算符,通常也需要相应地重载delete运算符,以确保内存的正确释放。 可以根据需要重载其他版本的newdelete运算符,例如带有额外参数的newdelete运算符,数组形式newdelete运算符等。重载这些运算符时需要遵循一定的规则和约定,确保正确性和可靠性。 值得注意的是,C++11引入了更加灵活和安全的内存管理方式,例如智能指针(如std::shared_ptr和std::unique_ptr)和RAII(资源获取即初始化)等,这些方式可以减少手动管理内存的复杂性和错误。因此,在使用newdelete运算符进行内存管理之前,建议先考虑这些更高级的内存管理工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值