考虑以下实现整数的二进制类表示:
class Binary {
private:
int *digits;
int first1;
public:
Binary() {
digits = new int[128];
digits[0]=0;
first1=0;
}
~Binary() {
cout<<"deleting"<<endl;
delete [] digits;
}
Binary(const Binary& b){
digits = new int[128];
memcpy(digits,b.digits,128*sizeof(int));
first1=b.first1;
}
explicit Binary(double x){
int n=(int)x,i;
digits = new int[128];
for (i=0; n ; i++,n>>=1) digits[i]=(n & 1)? 1:0;
first1=i-1;
}
Binary& operator =(const Binary& b){
if (this==&b) return *this;
memcpy(digits,b.digits,128*sizeof(int));
first1=b.first1;
return *this;
}
Binary(int n) {
int i;
digits = new int[128];
for (i=0; n ; i++,n>>=1) digits[i]=(n & 1)? 1:0;
first1=i-1;
}
void print() {
for (int i=first1; i>=0 ; i--) cout<<digits[i];
cout<<endl;
}
operator int() {
int x = 1,sum=0;
for (int i=0; i<=first1 ; i++,x<<=1) sum+=digits[i]*x;
return sum;
}
Binary& operator +(Binary& a) {
int overflow = 0;
Binary* b1=new Binary();
int max = a.first1>this->first1? a.first1 : this->first1,bit;
for (int i=0; i<=max ; i++) {
bit=a.digits[i]+this->digits[i]+overflow;
overflow=0;
if (bit>1) overflow=1;
b1->digits[i]=bit%2;
}
return *b1;
}
};
主要使用它:
int main() {
Binary b(91);
int x=9;
Binary *b2=new Binary();
*b2=b+x;
x=*b2;
b2->print();
cout<<" = "<<x;
cin>>x;
}
让我们谈谈这一行:
*b2=b+x;
首先,编译器隐式为int x分配一个新的二进制实例,然后使用它作为加法的参数,然后为加法结果创建一个新的二进制实例,并将其一点一点地复制到* b2。
问题是,如果运行此代码,它只打印删除ONCE,同时为执行命令创建了2个对象。显然有一个泄漏来自添加代码,其中我明确地创建了一个新对象来返回结果。
Q1 :我是对的吗?
Q2 :我该怎么做才能克服这个问题?
修改: 可以找到关于运算符重载主题的答案和更多内容here
答案 0 :(得分:2)
摘要:必须使用new
删除分配了delete
的对象。分配有new[]
的对象必须使用delete[]
删除。当其范围/ TU执行结束时,全局和本地会自动删除。在Binary& operator +(Binary& a)
中,您发布了泄露的Binary
,并在main
中创建了另一个泄露的Binary
。
如果像operator+
这样编写,则可以避免这些问题:
Binary operator +(Binary& a) const{ //return by value
Binary b1(*this); //hold it on the stack
//math here
return b1; //return by value
}
如果在主要部分你也避免分配:
Binary b2 = b+x;
x = b2;
b2.print();
这将比原始代码更快,更易于阅读和理解,并且不会泄漏。
[其他说明]
使用std::vector
作为内部数据,而不是管理自己的动态数组。 vector
更容易,也不太可能犯错误。
通常最好在任何地方进行转换(例如int
- &gt; Binary
)。它增加了打字,但可以减少头痛。这适用于您的int
转换运算符。
使const函数成为常量。现在,如果你得到一个const Binary
,你就不能用它做几乎所有的。你不能打印它,你不能添加任何东西......
您似乎每int
存储一位,这意味着您使用的空间比所需空间多97%(浪费了99.99999995%的值),这简直太傻了。大多数新手都以0-9
每char
开头,只占用了50%的空间。 (虽然这仍然是96%的值),但是很容易理解。
添加的正常方法是这样的:
Binary& operator+=(const Binary& rhs) {
int max = a.first1>this->first1? a.first1 : this->first1,bit;
for (int i=0; i<=max ; i++) {
bit=a.digits[i]+this->digits[i]+overflow;
overflow=0;
if (bit>1) overflow=1;
b1->digits[i]=bit%2;
}
}
Binary friend operator+(Binary lhs, const Binary& rhs) {
{return lhs+=rhs;}
答案 1 :(得分:0)
如果你真的只看到“删除”一次,那么这必须是变量b。 *b2 = b+x
可以通过将b转换为int,添加x,从中构造二进制并将其复制到b2指向的位置来完成。由于b2只是一个原始指针,因此泄漏了初始的* b2实例和覆盖它的那个实例。
答案 2 :(得分:0)
您不是在主页末尾删除b2。
运算符也应该按值返回,而不是返回一个已分配的二进制对象,因为它会泄漏,因为C ++不是垃圾回收
operator +也应该使用const引用。
另外,print,operator +和operator int应该是const成员函数
此外,您不需要动态分配128个整数,只需将其设为128个整数的数组
private:
int digits[128];
并删除数字删除
另外,您应该使用
在构造函数中初始化它memset(digits, 0, sizeof(digits));