找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3024|回复: 1

重识new

[复制链接]

307

主题

228

回帖

7349

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5599 个
贡献
253 次
宅之契约
0 份
在线时间
949 小时
注册时间
2014-1-25
发表于 2014-10-12 00:25:43 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
一、new primer
    new操作符并不是c++的专属,c运行库有new.h头文件。
    C++中的new操作符,众所周知是用来分配动态内存的,而要能达到“动态”这种灵活性的特征,非堆区莫属,因为堆区支持手动分配。如果内存空间不够,new操作符返回空,或抛出异常(下面会讲述3种new操作符,常规new操作符、定位new操作符和禁止抛出异常的new操作符,如果禁止抛异常,那么只好返回空了)
下面代码为MSDN中的,检测new分配是否成功,内存分配失败处理还可以通过_set_new_handler注册分配异常函数结果

  1. // insufficient_memory_conditions.cpp
  2. // compile with: /EHsc
  3. #include <iostream>
  4. using namespace std;
  5. #define BIG_NUMBER 100000000
  6. int main() {
  7.    int *pI = new int[BIG_NUMBER];
  8.    if( pI == 0x0 ) {
  9.       cout << "Insufficient memory" << endl;
  10.       return -1;
  11.    }
  12. }
复制代码


    对于对象使用new操作符的情况,生成的代码执行的流程一般为:先调用内部合适的new函数,该函数最终调用内存分配API进行堆内存分配,同时初始化一些方便内存管理的结构体和数据。成功分配后,将该地址视为this,如有必要则设置虚表指针,之后调用构造函数对该地址处对象进行构造。构造函数一般也是执行初始化功能而已,修改修改数据啥的。这些都是老生常谈不再赘述。
    即使请求的空间是0字节大小,new也会返回不同的地址,也就说总是在不同区域分配。这里注意和空类的区别,空类的大小是1,传给new函数(该函数在之后给出)之后,new函数接受到的参数只会>=1,而对于特殊情况:char* pch=new char[0];new函数接受的参数确实是0,不过分配的空间并不是0字节,因为存在内存管理相关的结构体也会占用内存。
    new操作符有2种作用域,一种是全局new,一种是类作用域new。用户在自定义类中可以重载自定义new函数。代码如下:

  1. #include <malloc.h>
  2. #include <memory.h>

  3. class Blanks
  4. {
  5. public:
  6.     Blanks(){}
  7.     void *operator new( size_t stAllocateBlock, char chInit );
  8. };
  9. void *Blanks::operator new( size_t stAllocateBlock, char chInit )
  10. {
  11.     void *pvTemp = malloc( stAllocateBlock );
  12.     if( pvTemp != 0 )
  13.         memset( pvTemp, chInit, stAllocateBlock );
  14.     return pvTemp;
  15. }
  16. // 对于Blanks对象,全局new操作符已被替换,因此下面的代码将分配sizeof(Blanks)大小的空间并把数据赋值为0xa5
  17. int main()
  18. {
  19.    Blanks *a5 = new(0xa5) Blanks;
  20.    return a5 != 0;
  21. }
复制代码


二、new primer plus
new和delete操作符是通过一种称为自由存储区的内存池分配内存的,而new和delete操作符本身在编译时会由编译器选择合适的new函数和delete函数进行实现。
C运行库的new函数会在失败时抛出std::bad_alloc异常,如果要使用不抛出异常的new版本,则需要链接nothrownew.obj,然而一旦链接了该文件,标准C++库中的new就不起作用了
new有2种语法形式
[::] new [placement] new-type-name [new-initializer]
[::] new [placement] ( type-name ) [new-initializer]

2种new函数原型为:
void* operator new( std::size_t _Count ) throw(bad_alloc);
void* operator new( std::size_t _Count, const std::nothrow_t& ) throw( );
void* operator new( std::size_t _Count, void* _Ptr ) throw( );


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( );


其用法如下:

  1. // new_op_new.cpp
  2. // compile with: /EHsc
  3. #include<new>
  4. #include<iostream>

  5. using namespace std;

  6. class MyClass
  7. {
  8. public:
  9.    MyClass( )
  10.    {
  11.       cout << "Construction MyClass." << this << endl;
  12.    };

  13.    ~MyClass( )
  14.    {
  15.       imember = 0; cout << "Destructing MyClass." << this << endl;
  16.    };
  17.    int imember;
  18. };

  19. int main( )
  20. {
  21.    // The first form of new delete
  22.    MyClass* fPtr = new MyClass;
  23.    delete fPtr;

  24.    // The second form of new delete
  25.    MyClass* fPtr2 = new( nothrow ) MyClass;
  26.    delete fPtr2;

  27.    // The third form of new delete
  28.    char x[sizeof( MyClass )];
  29.    MyClass* fPtr3 = new( &x[0] ) MyClass;
  30.    fPtr3 -> ~MyClass();
  31.    cout << "The address of x[0] is : " << ( void* )&x[0] << endl;
  32. }
复制代码

Construction MyClass.000B3F30
Destructing MyClass.000B3F30
Construction MyClass.000B3F30
Destructing MyClass.000B3F30
Construction MyClass.0023FC60
Destructing MyClass.0023FC60
The address of x[0] is : 0023FC60


  1. // new_op_alloc.cpp
  2. // compile with: /EHsc
  3. #include <new>
  4. #include <iostream>

  5. using namespace std;

  6. class MyClass {
  7. public:
  8.    MyClass() {
  9.       cout << "Construction MyClass." << this << endl;
  10.    };

  11.    ~MyClass() {
  12.       imember = 0; cout << "Destructing MyClass." << this << endl;
  13.       };
  14.    int imember;
  15. };

  16. int main() {
  17.    // The first form of new delete
  18.    MyClass* fPtr = new MyClass[2];
  19.    delete[ ] fPtr;

  20.    // The second form of new delete
  21.    char x[2 * sizeof( MyClass ) + sizeof(int)];
  22.    
  23.    MyClass* fPtr2 = new( &x[0] ) MyClass[2];
  24.    fPtr2[1].~MyClass();
  25.    fPtr2[0].~MyClass();
  26.    cout << "The address of x[0] is : " << ( void* )&x[0] << endl;

  27.    // The third form of new delete
  28.    MyClass* fPtr3 = new( nothrow ) MyClass[2];
  29.    delete[ ] fPtr3;
  30. }
复制代码


Construction MyClass.00311AEC
Construction MyClass.00311AF0
Destructing MyClass.00311AF0
Destructing MyClass.00311AEC
Construction MyClass.0012FED4
Construction MyClass.0012FED8
Destructing MyClass.0012FED8
Destructing MyClass.0012FED4
The address of x[0] is : 0012FED0
Construction MyClass.00311AEC
Construction MyClass.00311AF0
Destructing MyClass.00311AF0
Destructing MyClass.00311AEC


他们是怎么实现的呢?请听下回分解
回复

使用道具 举报

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24265 个
贡献
46222 次
宅之契约
0 份
在线时间
2299 小时
注册时间
2014-1-26
发表于 2014-10-12 14:34:17 | 显示全部楼层
哈哈 卖关子
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-5-6 04:35 , Processed in 0.034815 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表