[C++空间分配]new运算符、operator new、placement new的区别于联系
先科普一下:
1. new的执行过程:
(1)通过operator new申请内存
(2)使用placement new调用构造函数(内置类型忽略此步)
(3)返回内存指针
2. new和malloc的比较:
(1)new失败时会调用new_handler处理函数,malloc不会,失败时返回NULL
(2)new能通过placement new自动调用对象的构造函数,malloc不会
(3)new出来的东西是带类型的,malloc是void*,需要强制转换
(4)new是C++运算符,malloc是C标准库函数
3. delete的执行过程:
(1)调用析构函数(内置类型忽略此步)
(2)释放内存
4.delete和free的比较
(1)delete能自动调用对象的析构函数,malloc不会
(2)delete是C++运算符,free是C标准库函数
new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数。
new 运算符
(1)调用operator new分配足够的空间,并调用相关对象的构造函数
(2)不可以被重载
operator new
(1)只分配所要求的空间,不调用相关对象的构造函数。当无法满足所要求分配的空间时,则
->如果有new_handler,则调用new_handler,否则
->如果没要求不抛出异常(以nothrow参数表达),则执行bad_alloc异常,否则
->返回0
(2)可以被重载
(3)重载时,返回类型必须声明为void*
(4)重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t
(5)重载时,可以带其它参数
delete 与 delete operator类似
#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);//调用全局的operator new申请空间
} void operator delete(void* pointee)
{
cout<<"operator delete"<<endl;
::operator delete(pointee);//调用全局的operator delete释放空间
}
private:
int num;
}; int main()
{
X *px = new("A new class") X;
delete px; return 0;
}
注意::operator new是全局的函数,全局的这样的函数有三个,其中有一个就是placemet new,后面说。一般用户不会(虽然能)在全局重载operator new函数,而是在自定义的类中重载operator new函数。operator new都是申请一个对象的空间内存,所以调用的时候size_t省略,但是对于operator new[]这个函数,要明确的说明数组中对象的个数。
new和delete操作符我们应该都用过,它们是对堆中的内存进行申请和释放,而这两个都是不能被重载的。要实现不同的内存分配行为,需要重载operator new和operator delete,而不是new和delete。
operator new就像operator+一样,是可以重载的。但是不能在全局对原型为void operator new(size_t size)这个原型进行重载,一般只能在类中进行重载。如果类中没有重载operator new,那么调用的就是全局的::operator new来完成堆的分配。同理,operator new[]、operator delete、operator delete[]也是可以重载的。
至于placement new,只是operator new的一个重载的版本,只是我们很少用到它。如果你想在已经分配的内存中创建一个对象,使用new时行不通的。也就是说placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址。
我们知道使用new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。placement new就可以解决这个问题。我们构造对象都是在一个预先准备好了的内存缓冲区中进行,不需要查找内存,内存分配的时间是常数。而且不会出现在程序运行中途出现内存不足的异常。所以,placement new非常适合那些对时间要求比较高,长时间运行不希望被打断的应用程序。 placement new使用方法如下:
1. 缓冲区提前分配,可以使用堆的空间,也可以使用栈的空间。所以分配方式有如下两种:
class MyClass {…};
char *buf = new char[N * sizeof(MyClass)];
char buf[N * sizeof(MyClass)]; 2. 对象的构造
MyClass * pClass = new(buf) MyClass; //使用placement new 3. 对象的销毁
一旦这个对象使用完毕,你必须显式的调用类的析构函数进行销毁对象。但此时内存空间不会被释放,以便其他的对象的构造。
pClass->~MyClass(); 4. 内存的释放
如果缓冲区在堆中,那么调用delete[] buf 进行内存的释放。如果在栈中,那么在其作用域内有效,跳出作用域,内存自动释放。 补充说明:
在C++标准中,对于placement operator new []有如下的说明:
placement operator new[] needs implementation-defined amount of additional storage to save a size of array。
所以我们必须申请比原始对象大小多出sizeof(int)个字节来存放对象的个数,或者说数组的大小。
使用方法第二步中的new才是使用placement new,其实是没有申请内存的,只是调用了构造函数。
返回一个指向已经分配好的内存的一个指针,所以对象销毁的时候不需要调用delete释放空间,但必须调用析构函数销毁对象。
所以对于placement new用于对象数组的时候:
char *buf=new char[N*sizeof(MyClass)+sizeof(int)];
char buf[N*sizeof(MyClass)+sizeof(int)];
MyClass * pClass=new(buf) MyClass[N]; //使用placement new[]
前面说到了全局那里有三个operator new函数,下面看看:
operator new分为三种形式(前2种不调用构造函数,这点区别于new operator):
1: void* operator new (std::size_t size) throw (std::bad_alloc);
2: void* operator new (std::size_t size, const std::nothrow_t & nothrow_constant) throw();
3: void* operator new (std::size_t size, void* ptr) throw();
第一种分配size个字节的存储空间,并进行对象类型进行内存对齐。如果成功,返回一个非空的指针指向首地址。失败抛出bad_alloc异常。
第二种在分配失败时不抛出异常,它返回一个NULL指针。
第三种是placement new版本。它不分配内存,调用合适的构造函数在ptr所指的地方构造一个对象,之后返回实参指针ptr。
三种版本的operator new 定义在全局命名空间,不在std中。第一、第二个版本C++默认在每个编译单元中声明,不需要#include <new>头文件。第一、第二个版本可以被用户更换和重载(一般在类中重载),定义自己的版本,第三种placement new不可重载。
// operator new example
#include <iostream>
#include <new>
using namespace std; struct myclass {myclass() {cout <<"myclass constructed\n";}}; int main ()
{
int * p1 = new int;
// same as:
// int * p1 = (int*) operator new (sizeof(int)); int * p2 = new (nothrow) int;
// same as:
// int * p2 = (int*) operator new (sizeof(int),nothrow); myclass * p3 = (myclass*) operator new (sizeof(myclass));
// (!) not the same as:
// myclass * p3 = new myclass;
// (constructor not called by function call, even for non-POD types) new (p3) myclass; // calls constructor
// same as:
// operator new (sizeof(myclass),p3) return 0;
}
//结果输出:myclass constructed
[C++空间分配]new运算符、operator new、placement new的区别于联系的更多相关文章
- operator new,new operator,placement new的区别
原文地址:http://www.cnblogs.com/jamesmile/archive/2010/04/17/1714311.html,在此感谢 C++中的operator new与new ope ...
- Python第二天 变量 运算符与表达式 input()与raw_input()区别 字符编码 python转义符 字符串格式化 format函数字符串格式化 帮助
Python第二天 变量 运算符与表达式 input()与raw_input()区别 字符编码 python转义符 字符串格式化 format函数字符串格式化 帮助 目录 Pychar ...
- C++内存管理(new operator/operator new/operator delete/placement new)
new operator 我们平时使用的new是new操作符(new operator),就像sizeof一样是语言内置的,不能改变它的含义,功能也是一样的 比如: string *ps = new ...
- Swift学习(一):自定义运算符 operator
自定义运算符仅能包含这些字符: / = - + * % < >!& | ^.~ 运算符位置: 前置运算符 prefix 中间运算符 infix 后置运算符 postfix 运算符其 ...
- 【转】C++易混知识点3. New Operator, Operator New, Placement New 实例分析,比较区别
我们知道,C++中引入了New 这个内置符号,很大方便了指针的使用,程序员不必关注与这块堆上新分配的内存是如何来的,如何初始化的,然后如何转换为我们想要的类型指针的.现在,我们重点来分析下这个NEW内 ...
- c++中new/operator new/placement new
1. new/delete c++中的new(和对应的delete)是对堆内存进行申请和释放,且两个都不能被重载. 2. operator new/operator delete c++中如果想要实现 ...
- 重载运算符-operator
先看段代码: struct node { friend bool operator< (node n1, node n2){ // 优先取最小的,它与下面的 // 是等价的 return n1. ...
- 操作符(运算符)重载 或者叫 二元运算符 operator + 与 转换式操作符 implicit operator explicit operator
static void Main(string[] args) { rational r1 = new rational(5); rational r2 = new rational(51); rat ...
- 运算符 Operator 及优先级
算数运算符 + - * / ** % /表示自然除,结果是浮点数.//为整除.python2.x版本/和//都是整除. 位运算符 & | ~ ^ << >> <& ...
随机推荐
- Codeforces Round #245 (Div. 1)——Working out
题目链接 题意: 一个n*m的矩阵,每一个方格有一个非负数,如今选择两条线路:一个左上到右下,一个左下到右上,且仅仅能有一个公共点. 求两个线路上数的最大值(公共点不算) 分析: 仅仅有两种情况,dp ...
- NGUI 3.5过程(三)Button button
写在前面: 本文将创建一个主要的Button.而且编写脚本,响应点击事件. 欢迎大家纠错.拍砖.原创非常辛苦,如有转载,请注明出处. Button -- button 在NGUI 3.5 里, ...
- 如何使用Storyboard创建UIPageViewController
之前我们已经讲过UIPageViewController,那篇文章演示了如何使用Interface Builder创建UIPageViewController.为了适配iOS7和Xcode5,我们重新 ...
- vsts
首先要搞清楚啥是VSTS,这对于我们安装配置有基础作用.看看这张组织结构图就一目了然了.Visual Studio Team Suite就是我们常说的VS.NET 2005开发环境,安装包3G左右的 ...
- 初识动画animation
工作半年了,基本没怎么用到动画,现在对已学到的动画做一个总结(真的非常非常基础啊啊啊),准备之后再慢慢研究一下动画(有好的教程可以推荐给我咩~~). animation animation:mymov ...
- asp.net application
Application 对象用于存储和访问来自任何页面的变量,类似于 session 对象.不同之处在于,所有的用户分享一个 Application 对象,而 session 对象和用户的关系是一一对 ...
- IBATIS处理typeHandler类容易范的SQLException总结
1. java.sql.SQLException: 无效的列类型 原因: A. ibatis的IN,OUT参数.或者typeHandler类中传入的参数值数据类型与Oracle自定义对象中的属性值的数 ...
- iOS中有关配置 Apache 服务器的详细步骤
配置 Apache 服务器 目的: 能够有一个测试的服务器,Apache 服务器是免费的! 为什么是 Apache 使用最广的 Web 服务器 Mac自带,只需要修改几个配置就可以,简单,快捷 有些特 ...
- zoj1074 To the Max
题目很简单,求一个连续的最大子矩阵的值. zoj上的数据非常弱. 首先爆搜是O(N^4),10^8的复杂度略高,那么我们可以处理一下其中一维的前缀和,降一阶,然后按照连续最大子序列来处理,因为可能为负 ...
- mysql优化(3) 集群配置
两台服务器 192.168.187.131 192.168.187.132 1.主从配置 131为主 132为从 在131下 vim /etc/my.cnf [mysqld] datadir=/var ...