operate new()和new operate的区别

2024-01-26 23:48
文章标签 区别 new operate

本文主要是介绍operate new()和new operate的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

operator new 与 new operator

转载一篇 关于new的文章

 

operator new与new operator 收藏

C++中的operator new与new operator,看上去挺像的两姐妹,却有天壤之别。

operator new

(1) 只分配所要求的空间,不调用相关对象的构造函数。当无法满足所要求分配的空间时,则

        ->如果有new_handler,则调用new_handler,否则

        ->如果没要求不抛出异常(以nothrow参数表达),则执行bad_alloc异常,否则

        ->返回0

(2) 可以被重载

(3) 重载时,返回类型必须声明为void*

(4) 重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t

(5) 重载时,可以带其它参数

new operator

(1) 调用operator new分配足够的空间,并调用相关对象的构造函数

(2) 不可以被重载

相应地,operator delete与delete operator有相似的特性。

举个例子

class X 
{
public:
…………
    static void* operator new(size_t size)
{
    return ::operator new(size);
}
static void operator delete(void* pointee)
{
    ::operator delete(pointee);
}
…………
};
X* px = new X();

该行代码中的new为new operator,它将调用类X中的operator new,为该类的对象分配空间,然后调用当前实例的构造函数。

delete px;

该行代码中的delete为delete operator,它将调用该实例的析构函数,然后调用类X中的operator delete,以释放该实例占用的空间。

new operator与delete operator的行为是不能够也不应该被改变,这是C++标准作出的承诺。而operator new与operator delete和C语言中的malloc与free对应,只负责分配及释放空间。但使用operator new分配的空间必须使用operator delete来释放,而不能使用free,因为它们对内存使用的登记方式不同。反过来亦是一样。

你可以重载operator new和operator delete以实现对内存管理的不同要求,但你不能重载new operator或delete operator以改变它们的行为。

当重载operator new时,可以提供更多的参数,在new一个对象时,通过在关键字new后的括号传递额外的参数。比如以下的类

class A 
{
public:
    …………
    static void* operator new(size_t size, const string& example)
{
    cout << example << endl;
    return ::operator new(size);
}
…………
};
A* pa = new (“This will be printed out in operator new”) A();

新标准的C++允许以这样的方式传递一个名为nothrow的参数,以表明当为该对象分配空间失败时,不抛出异常,而是返回0,以兼容旧标准new的行为。比如

class B {};
B* pb = new (nothrow) B();

当然这只能对那些使用默认operator new操作符的类。对已经重载了operator new的类(比如上面的X和A),如果不声明能接受nothrow参数,自然无法享受C++标准带来的礼物。

 

operator new的六种重载形式

当写出
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来实现我们的内存分配方案.

这篇关于operate new()和new operate的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/648426

相关文章

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华

Python中的魔术方法__new__详解

《Python中的魔术方法__new__详解》:本文主要介绍Python中的魔术方法__new__的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、核心意义与机制1.1 构造过程原理1.2 与 __init__ 对比二、核心功能解析2.1 核心能力2.2

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

分辨率三兄弟LPI、DPI 和 PPI有什么区别? 搞清分辨率的那些事儿

《分辨率三兄弟LPI、DPI和PPI有什么区别?搞清分辨率的那些事儿》分辨率这个东西,真的是让人又爱又恨,为了搞清楚它,我可是翻阅了不少资料,最后发现“小7的背包”的解释最让我茅塞顿开,于是,我... 在谈到分辨率时,我们经常会遇到三个相似的缩写:PPI、DPI 和 LPI。虽然它们看起来差不多,但实际应用

GORM中Model和Table的区别及使用

《GORM中Model和Table的区别及使用》Model和Table是两种与数据库表交互的核心方法,但它们的用途和行为存在著差异,本文主要介绍了GORM中Model和Table的区别及使用,具有一... 目录1. Model 的作用与特点1.1 核心用途1.2 行为特点1.3 示例China编程代码2. Tab

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy