c++中的new、operator new、placement new
一、定义
1、new
new是c++中的关键字,,其行为总是一致的。它先调用operator new分配内存,然后调用构造函数初始化那段内存。
new 操作符的执行过程:
1. 调用operator new分配内存 ;
2. 调用构造函数在operator new返回的内存地址处生成类对象;
2、operator new
operator new是一个函数,就像重载任何一个符号如operator +,它用来分配内存(只不过new除了调用它还有其他步骤)。它可以被重载,通过重载它,可以改变new操作符的功能。它的功能介意类比c语言中的malloc,如果类中没有重载operator new,那么调用的就是全局的::operator new来从堆中分配内存。
2、placement new
placement new 是c++中对operator new 的一个标准、全局的重载版本。它并不分配内存,只是返回指向已经分配好的某段内存的一个指针,placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。
二、使用方法
1、new的使用
在堆上分配分配一块内存
struct A* i0 = new A;
struct A* i1 = new A();
看new的原型:
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
发现它有一个参数,size_t,表示前面调用placement new分配的内存大小,new接下来会在这块内存中调用构造函数,new的操作也是c++来保证的。
2、operator new的使用
分配8个字节的内存,因为是未重载,所以这里调用的是全局operator new,从堆上分配了8个字节
void* i = operator new ();
如果想重载operator new需要注意以下几点:
(1)重载时,返回类型必须声明为void*
(2)重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t
(3)重载时,可以带其它参数
(4)分配函数为类成员函数或全局函数;如果分配函数在全局范围之外的名称空间范围中声明,或者在全局范围中声明为静态,则程序是病态的
比如下面的例子中,在A重载了operator new打印出tag,返回全局的opereator new,然后在main函数中调用A的重载版本。
struct A{
int a;
char b;
void* operator new(size_t size,int tag) throw(){
cout << tag << endl;
return ::operator new(size);
}
};
int main()
{
void* i = A::operator new (,);
cout << i << endl;
return ;
}
最终结果即分配了内存,又打印出了tag的值

如果我们重载全局的operator new函数,然后调用new,则new的操作也会被更改,比如下面的例子(这个例子的operator new只有一个参数)
struct A{
int a;
char b;
};
void* operator new(size_t num) throw(){
cout << num << endl;
return nullptr;
}
int main()
{
A* i = new A;
cout << i << endl;
return ;
}
最终的结果是

可以看出,虽然没有直接调用operator new,但是new的操作已经被更改了。
还需要关注一个小地方,就是operator new调用时的参数和new的参数是有所区别的。new在调用的时候会忽略第一个size_t的参数,但是如果直接调用operator new来进行内存分配的时候是需要这个参数的。
也就是本节的第二个例子如果operator new的定义要像本节的第一个例子有两个参数的话,对new的调用应该如下:
A* i = new() A ;
3、placement new的使用
placement new是c++实现的operator new版本,它的实现如下
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; } // Default placement versions of operator delete.
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
//@}
可以看到实际上它就返回了传进来的地址,根据operator的第二个例子,通过重载全局的operator new之后,new函数的操作就被改变了。也就能猜出,在调用new的时候参数需要加上一个地址,placement new的功能就是在这个地址之上进行构造。
placement new的使用步骤如下
1)分配内存
char* buff = new char[ sizeof(Foo) * N ];
memset( buff, , sizeof(Foo)*N );
2)构建对象
Foo* pfoo = new (buff)Foo;
3)使用对象
pfoo->print();
pfoo->set_f(1.0f);
pfoo->get_f();
4)析构对象,显式的调用类的析构函数。
pfoo->~Foo();
5)销毁内存
delete [] buff;
上面5个步骤是标准的placement new的使用方法。
c++中的new、operator new、placement new的更多相关文章
- c++中new/operator new/placement new
1. new/delete c++中的new(和对应的delete)是对堆内存进行申请和释放,且两个都不能被重载. 2. operator new/operator delete c++中如果想要实现 ...
- C++中的new,operator new与placement new
以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下 new operator/delete operator就是new和 ...
- C++内存管理(new operator/operator new/operator delete/placement new)
new operator 我们平时使用的new是new操作符(new operator),就像sizeof一样是语言内置的,不能改变它的含义,功能也是一样的 比如: string *ps = new ...
- 【转】C++易混知识点3. New Operator, Operator New, Placement New 实例分析,比较区别
我们知道,C++中引入了New 这个内置符号,很大方便了指针的使用,程序员不必关注与这块堆上新分配的内存是如何来的,如何初始化的,然后如何转换为我们想要的类型指针的.现在,我们重点来分析下这个NEW内 ...
- [译]Javascript中的Ternary operator
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- C++中的定位放置new(placement new)
一般来说,使用new申请空间时,是从系统的“堆”(heap)中分配空间.申请所得的空间的位置时根据当时的内存的实际使用情况决定的.但是,在某些特殊情况下,可能需要在程序员指定的特定内存创建对象,这就是 ...
- 对于C++中const & T operator= 的一点思考
一个正常的assignment操作符的声明是这样的. const elmentType & elmentType::operator=(const elmentType &rhs) 这 ...
- C++中的new、operator new与placement new
转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new/delete与operator new/operator ...
- new 、operator new 和 placement new
一.原生operator new 我们先从原生operator new开始.考虑如下代码,它用来分配5个int型的空间并返回指向他们的指针[1]: int* v = static_cast<in ...
随机推荐
- expdp错误案例
转自:https://www.cnblogs.com/kerrycode/p/3960328.html Oracle数据泵(Data Dump)使用过程当中经常会遇到一些奇奇怪怪的错误案例,下面总结一 ...
- ssh 使用 sed 替换的时候,替换的字符串有单双引号的时候怎么用
线上有一个脚本需要 ssh 登录远程机,然后完成特定文件中的某个值,替换的字符中有单引号,所以需要特定的写法,才能成功 1).ssh 远程执行命令,替换字符串中有单引号( ' ) ssh zhuzi@ ...
- 初见SDN
软件定义网络(Software Defined Network, SDN ),是一种新型网络架构. SDN=OpenFlow:因为Openflow是大多数人唯一看得到的具体化的SDN的实现形式(实际上 ...
- Delphi ClientDataSet复制记录
数据源记录集:ClientDataSetSource:目标记录集:ClientDataSetCopy 1)复制一条记录. ClientDataSetCopy.Close; ClientDataSet ...
- Android APK安装过程学习笔记
1.什么是APK APK,即Android Package,Android安装包.不同平台的安装文件格式都不同,类似于Windows的安装包是二进制的exe格式,Mac的安装包是dmg格式.APK可以 ...
- vi命令详解(转)
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...
- sublimeText3编辑器 + 入门教程 + 使用大全
sublimeText3编辑器 + 入门教程 + 使用大全 Ctrl+D选中光标所占的文本,继续操作则会选中下一个相同的的文本 ctrl+G:输入行号,可快速跳转该行 ctrl+p:输入冒号,在输入行 ...
- itext实现pdf自动定位合同签订
需求 需要实现如下效果(最终效果) 思考 需求方的要求就是实现签订合同,实现方法不限,但过程中又提出需要在签章的过程中把签订日期的文字也打上去,这就有点坑了~ 一开始的想法是想办法定位需要签名的位置, ...
- MQ 简单的使用
需要创建两个控制台应用 引用用下面的包 (1)生产者 static void Main(string[] args) { ConnectionFactory factory = new Connect ...
- 写给深圳首期Python自动化开发周未班的信
你是否做了正确的决定? 深圳首期周未班的同学们大家好,我是Alex, 老男孩教育的联合创始人,Python项目的发起人,51CTO学院连续2届最受学员喜爱的讲师,中国最早一批使用Python的程序员, ...