zoukankan      html  css  js  c++  java
  • C++-new 的六种重载形式

    当写出这样的代码的时候, 实际上有两步操作:

    p = new P();

      1.分配内存,
      2.然后在分配好的内存之上初始化类成员.

    第二步是有构造函数完成的, 第一步就是new函数的工作.

    全局的new有六种重载形式, 

    void *operator new(std::size_t count)
        throw(std::bad_alloc);             //一般的版本
    
    void *operator new(std::size_t count,  //兼容早版本的new
        const std::nothrow_t&) throw();    //内存分配失败不会抛出异常
    
    void *operator new(std::size_t count, void *ptr) throw();
                                           //placement版本
    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();

      所以, 刚才的用法, 就是使用new函数的一种重载形式.
      如果A这个对象以同样实行重载了new函数的化, 作为成员函数会被优先调用.

    C++的各种new简介

    1.new T

      第一种new最简单,调用类的(如果重载了的话)或者全局的operator new分配空间,然后用类型后面列的参数来调用构造函数,用法是

    new TypeName(initial_args_list)

      如果没有参数,括号一般可以省略。例如:

    int *p=new int;
    int *p=new int(10);
    int *p=new foo("hello");


      通过调用delete来销毁:

    delete p;


    2. new T[]
      这种new用来创建一个动态的对象数组,他会调用对象的operator new[]来分配内存(如果没有则调用operator new,搜索顺序同上),然后调用对象的默认构造函数初始化每个对象。
      
      用法:

    new TypeName[num_of_objects];


      例如:

    int *p= new int[10];


      销毁时使用

    operator delete[]


    3.new()T 和new() T[]
      这是个带参数的new,这种形式的new会调用operator new(size_t,OtherType)来分配内存这里的OtherType要和new括号里的参数的类型兼容。
      这种语法通常用来在某个特定的地址构件对象,称为placement new,前提是operator new(size_t,void*)已经定义,通常编译器已经提供了一个实现,包含<new>头文件即可,这个实现只是简单的把参数的指定的地址返回,因而new()运算符就会在括号里的地址上创建对象。

      需要说明的是,第二个参数不是一定要是void*,可以识别的合法类型,这时候由C++的重载机制来决定调用那个operator new。

      当然,我们可以提供自己的operator new(size_,Type),来决定new的行为,比如

    char data[1000][sizeof(foo)];
    inline void* operator new(size_t ,int n)
    {
            return data[n];
    }


      就可以使用这样有趣的语法来创建对象:

    foo *p=new(6) foo(); //把对象创建在data的第六个单元上


      标准库还提供了一个nothrow的实现:

    void* operator new(std::size_t, const std::nothrow_t&) throw();
    void* operator new[](std::size_t, const std::nothrow_t&) throw();
    


      就可以实现调用new失败时不抛出异常

    new(nothrow) int(10);
    // nothrow 是std::nothrow_t的一个实例

      placement new 创建的对象不能直接delete来销毁,而是要调用对象的析够函数来销毁对象,至于对象所占的内存如何处理,要看这块内存的具体来源。

    4. operator new(size_t)
      这个的运算符分配参数指定大小的内存并返回首地址,可以为自定义的类重载这个运算符,方法就是在类里面声明加上

    void *operator new(size_t size)
    {
            //在这里分配内存并返回其地址
    }


      无论是否声明,类里面重载的各种operator new和operator delete都是具有static属性的一般不需要直接调用operator new,除非直接分配原始内存(这一点类似于C的malloc),在冲突的情况下要调用全局的operator加上::作用域运算符:

    ::operator new(1000); // 分配1000个字节


      返回的内存需要回收的话,调用对应的operator delete

    5.operator new[](size_t)

      这个也是分配内存,,只不过是专门针对数组,也就是new T[]这种形式,当然,需要时可以显式调用

    6.operator new(size_t size, OtherType other_value)
      和operator new[](size_t size, OtherType other_value)
      参见上面的new()
      需要强调的是,new用来创建对象并分配内存,它的行为是不可改变的,可以改变的是各种operator new,我们就可以通过重载operator new来实现我们的内存分配方案.

  • 相关阅读:
    记录python爬取猫眼票房排行榜(带stonefont字体网页),保存到text文件,csv文件和MongoDB数据库中
    分析Ajax来爬取今日头条街拍美图并保存到MongDB
    把SQLAlchemy查询对象转换成字典/json使用(汇总)
    把SQLAlchemy查询对象转换成字典/json使用(分开)
    使用Flask_SQLAlchemy连接多个数据库
    SQLAlchemy小知识点
    flask_sqlalchemy和sqlalchemy联系区别及其使用方式
    使用Requests+正则表达式爬取猫眼TOP100电影并保存到文件或MongoDB,并下载图片
    使用python脚本定时备份web网站
    使用shell脚本定时备份web网站代码
  • 原文地址:https://www.cnblogs.com/lemaden/p/10150665.html
Copyright © 2011-2022 走看看