我们知道,C++中引入了New 这个内置符号,很大方便了指针的使用,程序员不必关注与这块堆上新分配的内存是如何来的,如何初始化的,然后如何转换为我们想要的类型指针的。现在,我们重点来分析下这个NEW内置符号背后的步骤和所调用到的函数。这里面涉及到new operator, operator new, placement new.


转载请注明出处: http://blog.csdn.net/elfprincexu

1. New Operator (__type__ * a = new a();)

C 语言当中,我们在新申请一块内存的时候,通常使用的是malloc, 通常通过malloc(size_t size)来获得一块未初始化的raw memory。然后一般情况下我们会对该部分空间初始化(memset or memcpy)。

C++语言引入了new 操作符,极大地方便了使用,它一下子把C语言中的好几个步骤一下完成了,让我们觉得神奇的是,不必去深究其中的调用。

其实,new operator主要做了以下三个步骤的:

std::string* str = new std::string("memory management");// 例如,我们想申请一个新的string空间,其中空间并被初始化为“memory management”,并且该空间由一个stringlei类型的指针来指向,并把它返回给str。

1. 第一步,调用了 operator new 函数, operator new函数的作用 仅仅 是申请一块未被初始化的内存。

函数申明为:void* operator new (size_t size)

void* memory = operator new (sizeof("memory management"));// 申请足够大小的内存空间

2. 第二部,调用string 构造函数,在该未初始化的空间上初始化,也就是“memory management”

call string::string("memory management") on memory*

3. 第三部,将该指针转换为指定的想要的指针类型

string* str =  static_cast<std::string*> (memory);

总结下来:

(1)通过operator new申请内存

(2)使用placement new调用构造函数(简单类型忽略此步)

(3)返回内存指针

2. operator new (该函数仅仅 申请足够大小的内存,可以被重载)

void * operator new (size_t size);

举个例子来讲:

 1 // operator new example  
 2 #include <iostream>  
 3 #include <new>  
 4 using namespace std;  
 5    
 6 struct myclass {myclass() {cout <<"myclass constructed\n";}};  
 7    
 8 int main () {  
 9    
    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 ;  

28 }

重载operator new,

void * operator new (size_t size, string str);// 比如我们添加一个形参string, 用来辅助输出

调用

Base *b = new (“Operator new overload example”) Base;// str 形参放在new 后的挂号里面,

same as :

Base *b = (Base* ) ( operator new (sizeof(Base), "Operator new overload example") );

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
class Base {  
public:  
  Base() { }  
   
  void *operatornew(size_t size, string str ) {  
    cout << "Logging an allocation of " << size << " bytes for new object'" << str << "'" << endl;  
    return malloc( size );  
  }  
   
  int var;  
  double var2;  
};  
   
   

Base* b = new ("Base instance 1") Base;

输出: Logging an allocation of 12 bytes for new object 'Base instance 1'

3. Placement new. void* operator new ( size_t size, void* ptr) ;// ptr 会被返回,因为我们已经指定在已知的内存上

归根结底来讲,placement new 是operator new 的一种特殊重载,它不分配内存,只是调用合适的构造函数在ptr所指的地方构造一个对象,之后返回实参指针ptr。

例如:

myclass* p3 = static_cast<myclass*> ( operator new (sizeof(myclass));// p3 已经指定一块足够放下myclass对象的空间,该空间未初始化,

new (p3) myclass;// placement new, 在指定的p3空间上,call constructor myclass()来初始化该空间,并且返回p3.

1 // operator new example

 2 #include <iostream>  
 3 #include <new>  
 4 using namespace std;  
 5    
 6 struct myclass {myclass() {cout <<"myclass constructed\n";}};  
 7    
 8 int main () {  
 9    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 ;  
 }  

【转】C++易混知识点3. New Operator, Operator New, Placement New 实例分析,比较区别的更多相关文章

  1. 【转】 C++易混知识点4: 自己编写一个智能指针(Reference Counting)学习auto_ptr和reference counting

    这篇文章建大的介绍了如何编写一个智能指针. 介绍: 什么是智能指针?答案想必大家都知道,智能指针的目的就是更好的管理好内存和动态分配的资源,智能指针是一个智能的指针,顾名思义,他可以帮助我们管理内存. ...

  2. 【转】C++易混知识点1: 指针常量和常量指针的区别,附有详细案例解释

    熟悉C++也已经有一些年头了,今天突然翻出当年浏览的书籍,对一些概念居然生疏了,指针常量和常量指针由于 指针 这一特殊的对象而变得难以区别.因此,在思考再三之后,决定写下该篇总结,加强对他们的区别: ...

  3. 【转】 C++易混知识点2. 函数指针和指针函数的区别

    我们时常在C++开发中用到指针,指针的好处是开销很小,可以很方便的用来实现想要的功能,当然,这里也要涉及到指针的一些基本概念.指针不是基本数据类型,我们可以理解他为一种特殊类型的对象,他占据一定空间, ...

  4. 【转】C++易混知识点5:实例讲解Public Protected Private作用域,继承的区别和用意

    大学生涯,涉及到类的作用域,继承都是用的public 共有继承,当时也没想那么多,觉得共有继承多方便,多简单,反正没有太多的限制,不管是类的成员或者是基类的成员函数都可以访问.没有深究.其实这里面真是 ...

  5. JavaScript易错知识点整理

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  6. JavaScript 易错知识点整理

    本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一些ES ...

  7. SQL Server,Access数据库查询易混点和C#中parameter指定参数长度的优缺点

    在学校的时候就经常做一些网站,所以这次在公司实习,组长第一次给了一个企业的网站还是很快的完成了.中间并没有遇到什么大的问题,但是还是遇到了两个新手非常容易混淆的小问题,所以拿出来跟大家分享一下. 主要 ...

  8. JavaScript易错知识点整理[转]

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  9. JS易错知识点

    JAVASCRIPT易错知识点整理 前言 本文是学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由 ...

随机推荐

  1. php 抽象类和接口类

    PHP中抽象类和接口类都是特殊类,通常配合面向对象的多态性一起使用. 相同: ①两者都是抽象类,都不能实例化. ②只有接口类的实现类和抽象类的子类实现了 已经声明的 抽象方法才能被实例化. 不同: ① ...

  2. js中的稀疏数组和密集数组

    原文地址: http://www.2ality.com/2012/06/dense-arrays.html 一般来说JavaScript中的数组都是稀疏的,也就是说数组中的元素与元素之间是由空格的,因 ...

  3. 3DES加密

    本文介绍了3DES加密特性,加密特点,3DES是对称加密,用一个密钥对内容进行加密,必须使用相同的密钥进行解密, 密钥必须配置,而且长度为24位,不足24位,用0位进行补全,本文也顺带介绍了其它加密算 ...

  4. org.springframework.data.redis.serializer.SerializationException: Cannot serialize;

    前言 本文中提到的解决方案,源码地址在:perfect-ssm,希望可以帮你解决问题. 问题描述 在Spring与Redis整合过程中,出现了如下报错: org.springframework.dat ...

  5. 持续更新:从零开始的php学习生活

    其实也不是真的从零开始,在此之前我还是一边研究博学(博客美化)一边学的CSS.HTML.JavaScript的,相关内容可以戳这里. 看本文之前你最好稍微熟悉一下HTML.JavaScript什么的. ...

  6. BZOJ:4826: [Hnoi2017]影魔

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...

  7. STOI补番队互测#2

    Round2轮到我出了>_<(目测总共10人参加 实际共七人) 具体情况: #1: KPM,360 #2:ccz181078,160 #3:child,150 可惜KPM没看到第一题样例里 ...

  8. Codeforces__Raising Bacteria

    题目传送门:Raising Bacteria //问题描述:一个盒子里面放一个细菌在一天可以增生两个细菌. 现在已知盒子里面细菌的个数,问你最初放多少个细菌可以增生盒子里面的细菌数量 //输入:盒子中 ...

  9. 使用npm install报错-4048 operation not permitted解决

    刚刚使用npm install时一直报错-4048 operation not permitted,也尝试了多种方法,终于使问题得到解决,这里总结几种方法,先贴图: 一:权限问题 首先看到operat ...

  10. UEP-confirm和alert弹窗

    function stuDel(){ var ds = ajaxgrid.getCheckedRecords(); if(ds.length==0){ $.alert("提示信息" ...