new/delect表达式

本文详细介绍了C++中new和delete表达式的工作步骤,包括全局静态和类成员重载版本。重载new/delete可以自定义内存分配和释放行为。此外,还讨论了如何限制类对象只能在栈或堆上创建,以及内存管理在堆和栈对象中的不同。通过示例代码展示了如何实际应用这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

New/Delect表达式

一、new表达式工作步骤
使用new表达式时发生的三个步骤:

  1. 调用名为operator new的标准库函数,分配足够大的原始的未初始化的内存,以保存指定类型的一个对象
  2. 运行该类型的一个构造函数初始化对象
  3. 返回指向新分配并构造的构造函数对象的指针

二、delete表达式工作步骤
使用delete表达式时发生的两个步骤:

  1. 调用析构函数,回收对象中数据成员所申请的资源
  2. 调用名为operator delete的标准库函数释放该对象所用的内存
#include <string.h>                                                                                                                                                      
  #include <iostream>
  #include <string>
  #include <string.h>
  using std::cout;
  using std::endl;
  using std::string;

  //重载全局静态 ::operator new/delete,将导致其它类型new时使用重载过的 
  void * operator new(size_t sz)
  {
      /* printf("this : %p\n", this); //验证operator new是否含有this指针*/
      cout << "全局静态void *operator new(size_t)" << endl;

      void *ptr = malloc(sz);
      
      return ptr;
  }

 void operator delete(void *ptr)
  {
      /* printf("this : %p\n", this); */
      cout << "全局静态void operator delete (void *)" << endl;
      free(ptr);
  }

  void * operator new[](size_t size){
      void * ptr = malloc(size);
      cout << "全局静态operator new[](size_t size)" << endl;
      return ptr;
  }

 void operator delete[](void * ptr,size_t size){
      cout << "全局静态operator delete[](void * ptr,size_t size)" << endl;
      free(ptr);
  }
class Foo{                                                                                                                                                               
  public:
      Foo():_id(0){
          cout << "Foo() = " << this << " id = " << _id << endl;
      }
      Foo(int id,string name):_id(id),_name(name){
          cout << "Foo(int id) = " << this << " id = " << _id << endl; 
      }
      ~Foo(){
          cout << "~Foo() = " << this << " id = " << _id << endl; 
      }
      void print() const
      {
          cout << "id: " << _id << endl
               << "name: " << _name << endl;
      }
  public:
      //重载成员函数,静态,不含this指针
      void * operator new(size_t size,int num);
      void * operator new(size_t);
      void operator delete(void *,size_t);//size_t可选
      void operator delete(void * ptr,int num);
      void * operator new[](size_t);
      void operator delete[](void *,size_t);
  private:
      int _id;
      long _data;
      string _name;
  };

  void* Foo::operator new(size_t size){
      /* printf("this : %p\n", this); //验证operator new是否含有this指针*/
      Foo * ptr = (Foo *)malloc(size);
      cout << "成员函数Foo::operator new(size_t size)" << endl;
      return ptr;
  }

  void* Foo::operator new(size_t size,int num){
      Foo * ptr = (Foo *)malloc(size);
      cout << "重载后的成员函数Foo::operator new(size_t size,int num),num = " << num << endl;
      return ptr;
  }

 void Foo::operator delete(void * ptr,size_t size){
      cout << "成员函数Foo::operator delete(void * ptr,size_t size)" << endl;
      free(ptr);
  }


 void Foo::operator delete(void * ptr,int num){
      cout << "重载后的成员函数Foo::operator delete(void * ptr,int num)" << endl;
      free(ptr);
  }

  void* Foo::operator new[](size_t size){
      Foo * ptr = (Foo *)malloc(size);
      cout << "成员函数Foo::operator new[](size_t size)" << endl;
      return ptr;
  }

 void Foo::operator delete[](void * ptr,size_t size){
      cout << "成员函数Foo::operator delete[](void * ptr,size_t size)" << endl;
      free(ptr);
  }

void test1(){

      int N = 3;
      Foo * p = new Foo(1,"hello");
      //1     void * tmp = operator new(sizeof(Foo))
      //      p = static_cast<Foo*>(tmp);
      //2     p->Foo::Foo();
      //3     return p;
      p->print();
      delete p;
      //1     p->Foo::~Foo();
      //2     operator delect(p); 
      
      Foo * p1 = new Foo[N]();
      cout << sizeof(Foo[N]) <<  endl;
      
      //1     void * tmp = operator new(sizeof(Foo)*N + 4)
      //      p1 = static_cast<Foo*>(tmp);
      //2     p1->Foo::Foo();//N次
      //3     return p1;
      delete []p1;
      //1     p1->Foo::~Foo();//N次
      //2     operator delect(p1);    
      
      //调用的是全局函数
      Foo * p2 = ::new Foo();
      ::delete p2;

      Foo * p3 = ::new Foo[N]();
      ::delete []p3;
  }

void test2(){
	//重载全局静态的new/delete,将导致其它类型new/delete时使用的是重载后的
      string str = string("hello world");
      char * tmp = new char[strlen(str.c_str()) + 1];
      cout << str << endl;
      delete []tmp;
  }
  void test3(){
      //重载new/delete出多个版本,通过参数列表区分
      Foo *p4 = new (1024)Foo();
      delete p4;
  }
  int main(){
      test1();
      cout << endl << endl;
      test2();
      cout << endl << endl;
      test3();
      return 0;
  }   

在这里插入图片描述

  • 重载的new/delete和全局的new/delete都为静态的,没有this指针
  • 如果没有重载new/delete表达式,则使用的是全局静态的new/delete,重载了则使用重载的
  • 在重载了new/delete表达式的情况下,可以显示的使用全局静态的new/delete
  • 重载全局静态的new/delete,将导致其它类型new/delete时使用的是重载后的
  • new[N]/delete[]一个对象,new出来的大小为sizeof(Foo) * N + sizeof(int),sizeof(int)是数组大小,不同的编译器可能不一致

在这里插入图片描述

  • 可以重载new/delete出多个版本,但每一版的声明的参数列表都不相同,其中第一个参数必须为size_t,重载的出对应的delete只有在new所调用对象异常时,才会调用相应的delete回收未能完全创建对象的内存。
  • 堆对象时,析构函数是对象销毁的一部分,而栈对象,析构函数直接销毁对象,没有operator delete

三、要求一个类只能创建栈对象

  • 在创建出栈对象的同时,不能创建堆对象,operator new放入类的private区域

四、要求一个类只能创建堆对象

  • 在创建出堆对象的同时,不能创栈堆对象,析构函数放入类的private区域

内存。

  • 堆对象时,析构函数是对象销毁的一部分,而栈对象,析构函数直接销毁对象,没有operator delete

三、要求一个类只能创建栈对象

  • 在创建出栈对象的同时,不能创建堆对象,operator new放入类的private区域

四、要求一个类只能创建堆对象

  • 在创建出堆对象的同时,不能创栈堆对象,析构函数放入类的private区域
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值