1

整数のバイナリクラス表現の次の実装について考えてみます。

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にコピーします。

問題は、このコードを実行すると、コマンドの実行用に2つのオブジェクトが作成されているのに、1回だけ削除を出力することです。どうやら、追加コードからリークが発生しているようです。このコードでは、結果を返すために新しいオブジェクトを明示的に作成しました。

Q1:私は正しいですか?

Q2:これを克服するために何ができますか?

編集:演算子のオーバーロードのトピックに関する回答と詳細は、ここにあります

4

3 に答える 3

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独自の動的配列を管理する代わりに、内部データに a を使用します。vectorより簡単で、間違いを犯す可能性が低くなります。

通常は、変換 ( int->などBinary) を可能な限り明示的に行うのが最善です。タイピングが追加されますが、頭痛の種はなくなります。これは、int変換演算子にも当てはまります。

const 関数を const にします。現在、 を取得すると、ほとんど何もconst Binaryできなくなります。あなたはそれを印刷することも、それに何も追加することもできません...

ごとに 1 ビットを保存しているように見えintます。つまり、必要以上に約 97% 多くのスペースを使用していることを意味します (値の 99.99999995% を無駄にしています)。これはばかげています。ほとんどの初心者は0-9perから始め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;}
于 2012-07-06T00:39:07.890 に答える
0

メインの最後で b2 を削除していません。

また、C++ はガベージ コレクトされないため、割り当てられた Binary オブジェクトを返すのではなく、値で返す必要があります。

また、operator+ は const 参照を取る必要があります。

また、print、operator+、operator int は const メンバー関数にする必要があります。

また、128 int を動的に割り当てる必要はなく、128 int の配列にするだけです。

private:
    int digits[128];

数字の削除を削除します

また、コンストラクターで初期化する必要があります

memset(digits, 0, sizeof(digits));
于 2012-07-06T00:59:56.887 に答える
0

「削除」が実際に 1 回しか表示されない場合、これは変数 b である必要があります。*b2 = b+xb を int に変換し、x を追加し、そこから Binary を構築し、それを b2 が指す場所にコピーすることで実行できます。b2 は単なる生のポインターであるため、最初の *b2 インスタンスとそれを上書きするインスタンスをリークしています。

于 2012-07-05T21:59:39.833 に答える