设为首页 加入收藏

TOP

C++类和堆(一)
2013-04-10 11:54:24 来源: 作者: 【 】 浏览:744
Tags:类和

  一、构造函数和析构函数

  前面的例子已经运用了new和delete来为类对象分配和释放内存。当使用new为类对象分配内存时,编译器首先用new运算符分配内存,然后调用类的构造函数;类似的,当使用delete来释放内存时,编译器会首先调用泪的析构函数,然后再调用delete运算符。

  #include \"iostream.h\"

  class Date

  {

  int mo,da,yr;

  public:

  Date()  { cout<<\"Date constructor\"<<endl; }

  ~Date() { cout<<\"Date destructor\"<<endl; }

  }

  int main()

  {

  Date* dt = new Date;

  cout<<\"Process the date\"<<endl;

  delete dt;

  return 0;

  }

  程序定义了一个有构造函数和析构函数的Date类,这两个函数在执行时会显示一条信息。当new运算符初始化指针dt时,执行了构造函数,当delete运算符释放内存时,又执行了析构函数。

  程序输出如下:

  Date constructor

  Process the date

  Date destructor

  二、堆和类数组

  前面提到,类对象数组的每个元素都要调用构造函数和析构函数。下面的例子给出了一个错误的释放类数组所占用的内存的例子。

  #include \"iostream.h\"

  class Date

  {

  int mo, da, yr;

  public:

  Date()  { cout<<\"Date constructor\"<<endl; }

  ~Date() { cout<<\"Date destructor\"<<endl; }

  }

  int main()

  {

  Date* dt = new Date ;

  cout<<\"Process the date\"<<endl;

  delete dt;          //这儿

  return 0;

  }

  指针dt指向一个有五个元素的数组。按照数组的定义,编译器会让new运算符调用Date类的构造函数五次。但是delete被调用时,并没有明确告诉编译器指针指向的Date对象有几个,所以编译时,只会调用析构函数一次。下面是程序输出;

  Date constructor

  Date constructor

  Date constructor

  Date constructor

  Date constructor

  Process the date

  Date destructor

  为了解决这个问题,C++(www.cppentry.com)允许告诉delete运算符,正在删除的那个指针时指向数组的,程序修改如下:

  #include \"iostream.h\"

  class Date

  {

  int mo, da, yr;

  public:

  Date()  { cout<<\"Date constructor\"<<endl; }

  ~Date() { cout<<\"Date destructor\"<<endl; }

  }

  int main()

  {

  Date* dt = new Date ;

  cout<<\"Process the date\"<<endl;

  delete [] dt;          //这儿

  return 0;

  }

  最终输出为:

  Date constructor

  Date constructor

  Date constructor

  Date constructor

  Date constructor

  Process the date

  Date destructor

  Date destructor

  Date destructor

  Date destructor

  Date destructor

  三、重载new和delete运算符

  前面已经介绍了如何用new和delete运算符函数来动态第管理内存,在那些例子中使用的都是全局的new和delete运算符。我们可以重载全局的new和delete运算符,但这不是好的想法,除非在进行低级的系统上或者嵌入式编程(www.cppentry.com)。

  但是,在某个类的内部重载new和delete运算符时可以的。这允许一个类有它自己的new和delete运算符。当一个类需要和内存打交道时,采用这种方法来处理其中的细节,可以获得很搞的效率,同时避免了使用全局new和delete运算符带来的额外开销。因为全局堆操作时调用操作系统函数来分配和释放内存,这样效率很低。

  如果确定某个类在任何时候,其实例都不会超过一个确定的值,那么就可以一次性为类的所有实例分配足够的内存,然后用该类的new和delete运算符来管理这些内存。下面的程序说明了如何对new和delete进行重载。

  #include \"iostream.h\"

  #include \"string.h\"

  #include \"stddef.h\"

  #include \"new.h\"

  const int maxnames = 5;

  class Names

  {

  char name[25];

  static char Names::pool[];

  static bool Names::inuse[maxnames];

  public:

  Names(char* s)  { strncpy(name,s,sizeof(name)); }

  void* operator new(size_t) throw(bad_alloc);

  void operator delete(void*) throw();

  void display() const  { cout<<name<<endl; }

  };

  char Names::pool[maxnames * sizeof(Names)];

  bool Names::inuse[maxnames];

  void* Names::operator new(size_t) throw(bad_alloc)

  {

  for(int p=0; p<maxnames; p++)

  {

  if(!inuse[p])

  {

  inuse[p] = true;

  return pool+p*sizeof(Names);

  }

  }

  throw bad_alloc();

  }

  void Names::operator delete(void* p) throw()

  {

  if(p!=0)

  inuse[((char*)p - pool)/sizeof(Names)] = false;

  }

  int main()

  {

  Names* nm[maxnames];

  int i;

  for(i=0; i<maxnames; i++)

  {

  cout<<endl<<\"Enter name # \"<<i+1<<\":\";

  char name[25];

  cin >> name;

  nm[i] = new Names(name);

  }

  for(i=0; i<maxnames; i++)

  {

  nm[i]->display();

  delete nm[i];

  }

  return 0;

  }

   

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇定义另一个类的成员函数 下一篇求字符串的长度并返回

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: