一.new  
new operator就是new操作符,不能被重载,假如A是一个类,那么A * a=new A;实际上执行如下3个过程。  
(1)调用operator new分配内存,operator new (sizeof(A))  
(2)调用构造函数生成类对象,A::A()  
(3)返回相应指针  
事实上,分配内存这一操作就是由operator new(size_t)来完成的,如果类A重载了operator new,那么将调用A::operator new(size_t ),否则调用全局::operator new(size_t ),后者由C++默认提供。

二.operator new  
operator new是函数,分为三种形式(前2种不调用构造函数,这点区别于new operator):  
void* operator new (std::size_t size) throw (std::bad_alloc);  
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();  
void* operator new (std::size_t size, void* ptr) throw();  
第一种分配size个字节的存储空间,并将对象类型进行内存对齐。如果成功,返回一个非空的指针指向首地址。失败抛出bad_alloc异常。  
第二种在分配失败时不抛出异常,它返回一个NULL指针。  
第三种是placement new版本,它本质上是对operator new的重载,定义于#include <new>中。它不分配内存,调用合适的构造函数在ptr所指的地方构造一个对象,之后返回实参指针ptr。  
第一、第二个版本可以被用户重载,定义自己的版本,第三种placement new不可重载。  
A* a = new A; //调用第一种  
A* a = new(std::nothrow) A; //调用第二种  
new (p)A(); //调用第三种  
new (p)A()调用placement new之后,还会在p上调用A::A(),这里的p可以是堆中动态分配的内存,也可以是栈中缓冲。  
下面是重载operator new的一个例子:

#include <iostream>
#include <string>
using namespace std;class X
{
public:X(){cout << "X's constructor" << endl;}~X(){cout << "X's destructor" << endl;}void* operator new(size_t size, string str){cout << "operator new size " << size << " with string " << str << endl;return ::operator new(size);}void operator delete(void* pointer){cout << "operator delete" << endl;::operator delete(pointer);}
private:int num;
};int main()
{X *p = new("A new class") X;delete p;getchar();return 0;
}

运行结果:

三.placement new

一般来说,使用new申请空间时,是从系统的“堆”(heap)中分配空间。申请所得的空间的位置是根据当时的内存的实际使用情况决定的。但是,在某些特殊情况下,可能需要在已分配的特定内存创建对象,这就是所谓的“定位放置new”(placement new)操作。  
定位放置new操作的语法形式不同于普通的new操作。例如,一般都用如下语句A* p=new A;申请空间,而定位放置new操作则使用如下语句A* p=new (ptr)A;申请空间,其中ptr就是程序员指定的内存首地址。考察如下程序。

#include <iostream>
using namespace std;class A
{
public:A(){cout << "A's constructor" << endl;}~A(){cout << "A's destructor" << endl;}void show(){cout << "num:" << num << endl;}private:int num;
};int main()
{char mem[100];mem[0] = 'A';mem[1] = '\0';mem[2] = '\0';mem[3] = '\0';cout << (void*)mem << endl;A* p = new (mem)A;cout << p << endl;p->show();p->~A();getchar();
}

运行结果:   

阅读以上程序,注意以下几点。   
(1)用定位放置new操作,既可以在栈(stack)上生成对象,也可以在堆(heap)上生成对象。如本例就是在栈上生成一个对象。  
(2)使用语句A* p=new (mem) A;定位生成对象时,指针p和数组名mem指向同一片存储区。所以,与其说定位放置new操作是申请空间,还不如说是利用已经请好的空间,真正的申请空间的工作是在此之前完成的。  
(3)使用语句A *p=new (mem) A;定位生成对象时,会自动调用类A的构造函数,但是由于对象的空间不会自动释放(对象实际上是借用别人的空间),所以必须显示的调用类的析构函数,如本例中的p->~A()。  
(4)如果有这样一个场景,我们需要大量的申请一块类似的内存空间,然后又释放掉,比如在在一个server中对于客户端的请求,每个客户端的每一次上行数据我们都需要为此申请一块内存,当我们处理完请求给客户端下行回复时释放掉该内存,表面上看者符合c++的内存管理要求,没有什么错误,但是仔细想想很不合理,为什么我们每个请求都要重新申请一块内存呢,要知道每一次内从的申请,系统都要在内存中找到一块合适大小的连续的内存空间,这个过程是很慢的(相对而言),极端情况下,如果当前系统中有大量的内存碎片,并且我们申请的空间很大,甚至有可能失败。为什么我们不能共用一块我们事先准备好的内存呢?可以的,我们可以使用placement new来构造对象,那么就会在我们指定的内存空间中构造对象。  
下面是一个在堆上生成对象的例子。

#include <iostream>
using namespace std;class B
{
public:B(){cout<<"B's constructor"<<endl;}~B(){cout<<"B's destructor"<<endl;}void SetNum(int n){num = n;}int GetNum(){return num;}private:int num;
};int main()
{char* mem = new char[10 * sizeof(B)];cout << (void*)mem << endl;B *p = new(mem)B;cout << p << endl;p->SetNum(10);cout << p->GetNum() << endl;p->~B();delete[]mem;getchar();
}

运行结果:

C++中使用placement new相关推荐

  1. SAP WM中阶下架策略A(Partial Pallet Quantity)

    SAP WM中阶下架策略A(Partial Pallet Quantity) SAP WM模块中,下架策略A(Partial Pallet Quantity)也比较常用.放在仓库里的物料,有零托的,有 ...

  2. c语言全局变量符号,C语言中的 @ 符号是什么意思?

    标签:assign   inter   res   ted   访问内存   变量   出现   read_only   his Global Variable Address Modifier (@ ...

  3. Visual C++ 中的重大更改

    为什么80%的码农都做不了架构师?>>>    此文章由人工翻译. 将光标移到文章的句子上,以查看原文. 更多信息. Visual C++ 中的重大更改 Visual Studio ...

  4. operator new在C++中的各种写法

    乍一看,在C++中动态分配内存很简单:new是分配,delete是释放,就这么简单.然而,这篇文章讲得要复杂一点,并且要考虑到自定义层次.这也许对简单的程序并不重要,但对你在代码中控制内存却是十分必要 ...

  5. 数字IC后端流程——(三)布局Placement

    参考原博地址:https://blog.csdn.net/weixin_46752319/article/details/107360843 ICC布局阶段 在布局规划阶段完成了芯片的整体规划,而布局 ...

  6. ICC图文流程——(三)布局Placement

    ICC布局阶段 在布局规划阶段完成了芯片的整体规划,而布局阶段主要是软件自动的标准单元的摆放. 在布局开始之前,需要对设计进行确认和检查. 主要确认内容包括: ·检查设计中的所有macro是否设置为d ...

  7. Placement Rules 使用文档

    注意 本文介绍如何手动在 Placement Driver (PD) 中设置 Placement Rules.推荐使用 Placement Rules in SQL,让你更方便地设置表和分区的放置. ...

  8. Placement service – placement安装(wallaby-allinone)

    Placement service – placement安装(wallaby-allinone) 1 必须 在安装和配置放置服务之前,您必须创建数据库.服务凭证和 API 端点. 创建数据库 要创建 ...

  9. OpenStack Victoria搭建(七)安装并验证 Placement

    介绍 ✔ 笔记 在 Stein 发布之前,放置代码与计算 REST API 代码 (nova-api) 一起在 Nova 中.确保本文档的发布版本与您要部署的发布版本匹配. 步骤概述 部署API服务 ...

最新文章

  1. c语言延时函数_介召几个frida在安卓逆向中使用的脚本以及延时Hook手法
  2. linux下单节点oracle数据库间ogg搭建
  3. jittor和pytorch生成网络对比之cgan
  4. 0122 - EOS 编程学习日志(1)
  5. 从“执行新过程新增5%的工作量”看新过程引入
  6. 深度学习(十六)——Faster R-CNN, YOLO
  7. 电大计算机应用基础试卷号2007,电大计算机应用基础(试卷版)计算机试卷7.doc...
  8. linux查看r的安装路径,在Linux CentOS 6.5版上安装R3.1.1的问题(检查LDFLAGS以获取Fortran库的路径)...
  9. linux防火墙测试,构建基于ipchains的Linux防火墙
  10. oracle 数据结构部署,
  11. 局域网内如何设置多个ip地址分配
  12. 185.部门工资前三高的员工
  13. 笔记本计算机故障与诊断,笔记本电脑维护与故障诊断
  14. 批量删除多个 PPT 空白页
  15. word07 去掉标题前的黑点
  16. tf卡无法格式化怎么修复?解决方法分享
  17. MultiButton | 一个小巧简单易用的事件驱动型按键驱动模块
  18. UFS详细介绍---终章
  19. java哪个软件编程好学吗_java编程好学吗?
  20. sprintf() 用法

热门文章

  1. GitLab复习资料整理
  2. NTC热敏电阻基础以及应用和选择(转)
  3. NTC热敏电阻电阻与温度之间的转换公式
  4. Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值
  5. Labview 编写TCP/IP 客户端断线重连机制程序,亲测可用
  6. 监督学习(supervised learning)与非监督学习(unsupervised learning)
  7. Java集合系列(一):List、Map、Set的基本实现原理总结
  8. Androd studio无线调试及镜像投屏
  9. SAP FICO 财务月结--自动清账
  10. java编译方法参数(-parameters)名为arg0问题