LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2386|回复: 29

[求助]C++中运算符重载时出错

[复制链接]
发表于 2003-6-22 22:07:53 | 显示全部楼层 |阅读模式
小弟初学C++,写了一个高精度类作为练习,在调试的时候发现有时会出现缓冲区溢出的问题,经过N天的查找,发现是出在重载运算符的时候.

  我定义了hInt这样一个高精度类,对很多运算符进行了重载,返回类型都是hInt,而在operator+这个函数中,用hInt h;申请了一个临时变量,最后返回的也是它,这样,在函数调用完成时,h已经释放了,返回值就失去了意义.
  于是,我改成了hInt * h; h=new hInt; 返回时用return *h; 这样返回值就有意义了程序也正常运行了,但经过调试发现又带来了新的问题:这个临时变量没有机会被释放.所以当进行长时间运算后,内存就会不够用了.
  然后我就不知道究竟该怎样处理这个问题了.

  这里问一下大家,运算符重载时正确的方法是怎样的.要是有人能给我详细地说明一下C++中函数返回值的过程是怎样的就更好了
  多谢
发表于 2003-6-22 22:10:09 | 显示全部楼层
你的复制构造函数是怎么定义的?
发表于 2003-6-22 22:29:48 | 显示全部楼层
你的operator+返回的是什么类型?
hInt还是hInt&
 楼主| 发表于 2003-6-22 23:01:13 | 显示全部楼层
由于是高精度类,所以有一个char * number的私有指针用来保存数字,构造就是简单的number=new char[1],然后在以后用的时候先计算该有多少位数字(用length变量保存),再delete []number; number=new char[length];
析构就是 delete []number;

operator+返回的是hInt &
 楼主| 发表于 2003-6-22 23:03:27 | 显示全部楼层

我把源程序中必要的部分传上来

const int BASE=10;
class hInt
{
  private:
    int    sign;
    int    length;
    char * number;

    void new_number(int);
    void check();

    void abs_add(const hInt &,const hInt &);
    void abs_sub(const hInt &,const hInt &);
    int  abs_bes(const hInt &);
  public:
    hInt();
    hInt(char *);
    ~hInt();
    void to_str(char *);

    void operator=(const hInt &);
    void operator=(char *);
    hInt friend & operator+(const hInt &,const hInt &);
};
//private
void hInt::new_number(int i)
{
  delete []number;
  number=new char[i+1]; //note:char is not necessary
  number=0;      //but let char=0 can make it easy to watch
}
void hInt::check()
{
  if(length<0) return; //error, maybe no chance to happen
  if(length==0) { sign=0; return; }
  char * p=number+length-1;
  while((*(p--)==0)&&(length>0)) length--;
  if(length==0) sign=0;
}
void hInt::abs_add(const hInt & ha,const hInt & hb)
{
  //length and number[] will be made up here, but nothing to do with sign
  int l1,l2;
  char * p1, * p2;
  if(ha.length>hb.length)
  { l1=ha.length; l2=hb.length; p1=ha.number; p2=hb.number; }
  else
  { l2=ha.length; l1=hb.length; p2=ha.number; p1=hb.number; }
  length=l1+1;
  new_number(length);
  char * p=number;
  int i;
  char t=0;
  for(i=0;i<l2;i++)
  {
    t+=*(p1++)+*(p2++);
    if(t>=BASE) { *(p++)=t-BASE; t=1; }
    else        { *(p++)=t     ; t=0; }
  }
  for(;i<l1;i++)
  {
    t+=*(p1++);
    if(t>=BASE) { *(p++)=t-BASE; t=1; }
    else        { *(p++)=t     ; t=0; }
  }
  *p=t;
}
void hInt::abs_sub(const hInt & ha,const hInt & hb)
{
  //abs(ha) mustn't be smaller than abs(hb)
  int l1=ha.length, l2=hb.length;
  char * p1=ha.number, * p2=hb.number;
  length=l1;
  new_number(length);
  char * p=number;
  int i;
  char t=0;
  for(i=0;i<l2;i++)
  {
    t+=*(p1++)-*(p2++);
    if(t>=0) { *(p++)=t     ; t= 0; }
    else     { *(p++)=t+BASE; t=-1; }
  }
  for(;i<l1;i++)
  {
    t+=*(p1++);
    if(t>=0) { *(p++)=t     ; t= 0; }
    else     { *(p++)=t+BASE; t=-1; }
  }
}
int hInt::abs_bes(const hInt & h)
{
  if(length>h.length) return 1;
  if(length<h.length) return -1;
  char * p1=number+length-1, * p2=h.number+length-1;
  for(int i=0;i<length;i++)
  {
    if(*p1>*p2) return 1;
    if(*p1<*p2) return -1;
    p1--; p2--;
  }
  return 0;
}
//public
hInt::hInt()
{
  number=new char[1];
}
hInt::hInt(char * s)
{
  number=new char[1];
  *this=s;
}
hInt::~hInt()
{
  delete []number;
}
void hInt::to_str(char * s)
{
  char * p=number+length-1;
  if(sign==-1) *(s++)='-';
  for(int i=0;i<length;i++) *(s++)=*(p--)+'0';
  if(i==0) *(s++)='0';
  *s=0;
}
void hInt:perator=(const hInt & h)
{
  sign=h.sign;
  length=h.length;
  new_number(length);
  char * p1=number;
  char * p2=h.number;
  for(int i=0;i<length;i++) *(p1++)=*(p2++);
}
void hInt:perator=(char * s)
{
  while(*s==' ') s++;
  sign=1;
  if(*s=='-') { sign=-1; s++; }
  if(*s=='+') s++;
  length=0;
  while((s[length]>='0')&&(s[length]<='9')) length++;
  if(length==0) return; //error
  new_number(length);
  for(int i=0;i<length;i++) number[length-i-1]=s-'0';
  check();
}
hInt & operator+(const hInt & ha,const hInt & hb)
{
  hInt * h;
  h=new hInt;
  if(hb.sign==0) { *h=ha; return *h; }
  if(ha.sign==0) { *h=hb; return *h; }
  if(ha.sign==hb.sign)
  {
    h->sign=ha.sign;
    h->abs_add(ha,hb);
    h->check();
    return *h;
  }
  else
  {
    int t=ha.abs_bes(hb);
    if(t==0)
    {
      h->sign=0;
      h->length=1;
      h->new_number(1);
      *h->number=0;
      return *h;
    }
    if(t==1)
    {
      h->sign=ha.sign;
      h->abs_sub(ha,hb);
      h->check();
      return *h;
    }
    h->sign=hb.sign;
    h->abs_sub(hb,ha);
    h->check();
    return *h;
  }
}
//---------------------------------------------------------------------------
#include <iostream.h>
void set_str(char * t,const char * f)
{
  while(*(t++)=*(f++)) ;
}
void main()
{
  cout<<"test begin"<<endl;
  char s[256];
  hInt h1("1"),h2("9"),h3;
  h3=h1+h2;
  h3.to_str(s);
  cout<<s<<endl;
  cout<<"test end"<<endl;
}
//---------------------------------------------------------------------------
 楼主| 发表于 2003-6-22 23:04:48 | 显示全部楼层
呀,缩进没有了!
发表于 2003-6-22 23:46:03 | 显示全部楼层
首先,类里面要分配内存的话应该提供复制构造函数,
其次,返回局部变量应该返回值类型,不要返回引用。
发表于 2003-6-23 00:35:52 | 显示全部楼层
你好像是从c转过来的吧
发表于 2003-6-23 10:56:37 | 显示全部楼层
对,不能返回引用。也不要返回指针变换成的引用。
 楼主| 发表于 2003-6-23 11:20:53 | 显示全部楼层
我确实是从PASCAL和C转过来的.
至于各位提到的解决方案没太明白,能不能详细点介绍一下.
真是感激不尽!

我非常想知道一个函数返回值的时候是怎样一个过程,这里好像怎么都会出现内存泄漏的问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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