有段时间我一直在为班级解题,这次解了一个关于100进制数的问题,这个问题完全解决了,所有的测试都通过了。
但据说节目中有一些“失误”。一些发现,纠正。但还有更多。尽管该程序可以运行,但我认为没有任何原因会导致内存泄漏或其他问题。赋值运算符,似乎写得对,在运算符的重载中我写的不是对象作为参数,而是它的地址,所以最终没有创建对象的副本,没有泄漏,复制构造函数不需要,我就不写了。析构函数已编写。
我不明白会有什么样的失误。它似乎一直在正常学习课程。如果你知道,我们来讨论。
#include <iostream>
#include <cmath>
using namespace std;
class Sto{
int *data;
int size, sign;
public:
Sto(int asize)
{
size=asize;
data = new int[size];
sign=1;
}
~Sto()
{
delete[] data;
size = sign = 0;
}
Sto& operator=(const Sto& ob)
{
if (this == &ob)
return *this;
if (data) delete[] data;
size=ob.size;
sign=ob.sign;
data=new int[size];
for(int i=0;i<size;i++)
data[i]=ob.data[i];
return *this;
}
friend Sto operator+(const Sto &x, const Sto &y);
friend Sto operator*(const Sto &x, const int &chislo);
void scan()
{
int x_p=0;
cout<<"Vvedite "<<size<<" cifri\n";
for(int i=0; i<size; i++)
cin>>*(data+i);
while(data[x_p]==0) x_p++;
sign = (data[x_p] > 0) - (data[x_p] < 0);
data[x_p]=abs(data[x_p]);
}
void print(){
int x_p=0;
while(data[x_p]==0) x_p++;
cout<<sign*data[x_p]<<" ";
for(int i=x_p+1; i<size; i++)
cout<<data[i]<<" ";
}
};
Sto operator+(const Sto &x, const Sto &y)
{
Sto z(max(x.size,y.size)+1);
int x_i=x.size-1, y_i=y.size-1, z_i=z.size-1, tmp1=0, tmp2=0, major=1, x_p=0, y_p=0;
while(x.data[x_p]==0) x_p++;
while(y.data[y_p]==0) y_p++;
if(x.sign!=y.sign && x.size - x_p <= y.size - y_p)
{
if(x.size - x_p < y.size - y_p) major = -1;
else
{
for(int i=x_p, j=y_p; i<x.size; i++, j++)
if(x.data[i] < y.data[j]) { major = -1; break; }
}
}
if(x.sign == y.sign && x.sign==-1 || x.sign==-1 && major==1 || y.sign==-1 && major==-1) z.sign=-1;
while(z_i>=0)
{
tmp1 = 0; z.data[z_i] =0;
if(x_i>=x_p) z.data[z_i] += major * x.data[x_i];
if(y_i>=y_p) z.data[z_i] += major * (x.sign * y.sign) * y.data[y_i];
if(x.sign==y.sign)
{
if(y_i>=y_p-1 && y_i<y.size-1) tmp1 += y.data[y_i+1];
if(x_i>=x_p-1 && x_i<x.size-1) tmp1 += x.data[x_i+1];
z.data[z_i]+= tmp1/100;
if(z_i==1 && z.data[1]>=100)
z.data[0] = z.data[1]/100;
z.data[z_i] %=100;
}
else
{
z.data[z_i]-=tmp2;
if(z.data[z_i] < 0) {z.data[z_i]+=100; tmp2 = 1;} else tmp2=0;
}
x_i--; y_i--; z_i--;
}
return z;
}
Sto operator*(const Sto &x, const int &chislo)
{
Sto z(x.size + 1 + log(abs(chislo))/log(100) + 1);
int x_i=x.size-1, z_i=z.size-1, temp=0, x_p=0;
z.sign=1; if(x.sign * chislo < 0) z.sign=-1;
while(x.data[x_p]==0) x_p++;
while(z_i>=0)
{
z.data[z_i] = temp;
if(x_i>=x_p) z.data[z_i] += x.data[x_i]*abs(chislo);
temp = z.data[z_i]/100;
z.data[z_i] = z.data[z_i]%100;
x_i--; z_i--;
}
return z;
}
int main()
{
int size_x, size_y, number;
cout<<"Vvedite razmer 1-go massiva"<<endl;
cin>>size_x;
Sto ob1(size_x);
ob1.scan();
cout<<"\nVvedite razmer 2-go massiva"<<endl;
cin>>size_y;
Sto ob2(size_y);
ob2.scan();
Sto ob3(max(size_x,size_y)+1);
ob3 = ob1 + ob2;
cout<<"\nVvedite konstantu"<<endl;
cin>>number;
Sto ob4(size_x + 1 + log(abs(number))/log(100)+1);
ob4 = ob1 * number;
cout<<"\nSlojeniye dvux storichnix chisel: "; ob3.print();
cout<<"\nUmnojeniye ob1 na konstantu: "; ob4.print();
return 0;
}
我至少看到了七个问题:
首先,您使用的是原始指针而不是
std::unique_ptr. 使用智能指针会自动节省您编写析构函数的时间。它还禁用自动生成的复制构造函数。其次,您的析构函数正在做无用的工作。赋值
sign = size = 0没有意义,因为下一步会在析构函数后释放内存时销毁这些值。第三,您的析构函数未声明为虚拟的。如果有人从您的类继承,则析构函数链将无法正常工作。您应该将析构函数声明为虚拟的,或者添加
final到类声明中:如果您将代码保持原样,它将导致将来出现问题。
第四,对于 C++ 中的大小,有一个
size_t,你应该使用它而不是int.第五,如果您将数字存储在
std::vector. 这是使用原始指针解决问题 1 的另一种方法。第六 - 前缀递增和递减总是比后缀更可取,最好使用它们(
++i更好i++)第七字段初始化不应该在构造函数的主体中进行,而是在字段初始化列表中进行:
符号 (
sign) 应该更早地初始化 - 在类声明中。值越早初始化越好。此外,代码格式存在许多问题。通常,代码格式化是一个相当主观的事情,并受公司的代码风格指南的约束。但是,您应用的一些技术被认为是不可取的:
在这种情况下,我们同时遇到两个问题:
第一的。很长的一行,在某些显示器上必须滚动才能查看。
第二。一行上的多个广告。大多数样式指南都遵循“一行 - 一个声明”原则。这使您可以更清楚地突出新实体的外观,为评论留出空间并防止表单出现有趣的错误: