0

プロジェクトの場合、ビットセットクラスを実装する必要があります。これまでの私のコードは次のとおりです。

ヘッダーファイル

#ifndef BITSET_H_
#define BITSET_H_
#include <string>
#include <cmath>

using namespace std;

// Container class to hold and manipulate bitsets
class Bitset {
public:
    Bitset();
    Bitset(const string);
    ~Bitset();

    // Returns the size of the bitset
    int size();

    // Sets a bitset equal to the specified value
    void operator= (const string);

    // Accesses a specific bit from the bitset
    bool operator[] (const int) const;

private:
    unsigned char *bitset;
    int set_size;
    // Sets a bitset equal to the specified value
    void assign(const string);
};
#endif /* BITSET_H_ */

ソースファイル

#include "bitset.h"

Bitset::Bitset() {
    bitset = NULL;
}

Bitset::Bitset(const string value) {
    bitset = NULL;
    assign(value);
}

Bitset::~Bitset() {
    if (bitset != NULL) {
        delete[] bitset;
    }
}

int Bitset::size() {
    return set_size;
}

void Bitset::operator= (const string value) {
    assign(value);
}

bool Bitset::operator[] (const int index) const {
    int offset;

    if (index >= set_size) {
        return false;
    }

    offset = (int) index/sizeof(unsigned char);
    return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}

void Bitset::assign(const string value) {
    int i, offset;

    if (bitset != NULL) {
        delete[] bitset;
    }

    bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];

    for (i = 0; i < value.length(); i++) {
        offset = (int) i/sizeof(unsigned char);
        if (value[i] == '1') {
            bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
        } else {
            bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
        }
    }

    set_size = value.length();
}

私の問題は、deconstructorとassignメソッドのコアダンプの両方でのdeleteステートメントです。このメモリの割り当てを解除する必要はありませんか?これまで読んだことから、newを呼び出すときは常にdeleteコマンドを使用する必要があります。

編集:修正の1つを反映するために、上記のコードを変更しました。コンストラクターにビットセット=NULLを追加しました。これにより、assignメソッドのコアダンプが修正されましたが、デコンストラクターでエラーが発生します。

4

3 に答える 3

4

2番目のコンストラクターで初期化bitsetする必要があると思います。NULL

なんで?

ポインター変数は必ずしも に初期化されるとは限らないためNULLです。delete[]そのため、その 2 番目のコンストラクターを使用するときに、ランダムなメモリ アドレスを使用しようとしている可能性があります。

したがって、次のものが必要です。

Bitset::Bitset(const string value) : bitset(NULL)
{
    assign(value);
}
于 2010-11-16T02:50:39.317 に答える
1

ほとんどの場合、Bitsetどこかにコピーしています。コピー代入演算子ではなく、コピーコンストラクターを定義していません。コピーの結果、2つのインスタンスが作成され、終了時に動的に割り当てられた配列の割り当てを解除する必要があると考えられます。

これは、三つのルールとして知られています。デストラクタ、コピーコンストラクタ、またはコピー代入演算子のいずれかを定義する場合、3つすべてを定義する必要がある可能性があります。

さて、あなたのコードについて:

#include "bitset.h"

わかった。

Bitset::Bitset() {
    bitset = NULL;
}

(1)定義を保証するヘッダーを含めませんでしたNULL

(2)メンバーset_sizeを初期化していないため、インデックス演算子のチェックでは、未定義動作の不確定な値が使用される場合があります。

(3)一般に、代入よりも初期化子リストを使用することを好みます(これにより、たとえば、デフォルトの構築に続いて代入を行うことを回避できます)。

Bitset::Bitset(const string value) {
    bitset = NULL;
    assign(value);
}

(4)一般的に、割り当ての観点から構造を表現することはお勧めできません。代わりに、構造の観点から割り当てを表現します。

Bitset::~Bitset() {
    if (bitset != NULL) {
        delete[] bitset;
    }
}

(5)のチェックNULLは不要です。あなたは安全deleteにnullpointerをすることができます。

int Bitset::size() {
    return set_size;
}

(6)ええと、set_size初期化されていないメンバーでした…また、このメンバー関数はである必要がありますconst

void Bitset::operator= (const string value) {
    assign(value);
}

(7)代入演算子は、一般に、代入先オブジェクトへの参照を返す必要があります。これは単なる慣例ですが、クラスのユーザーが期待することです。

(8)引数を値またはへの参照で渡しますconst。一般に、組み込みタイプの場合は値による選択を選択し、などの他のタイプの場合は、へのstd::string参照を選択しますconst。つまり、正式な引数はである必要がありますstring const& value

bool Bitset::operator[] (const int index) const {
    int offset;

    if (index >= set_size) {
        return false;
    }

    offset = (int) index/sizeof(unsigned char);
    return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}

(9)まず、初期化されていないset_sizeメンバーです。

sizeof(unsigned char)(10)次に、定義上1であることに注意してください。CHAR_BITここから使いたいと思い<limits.h>ます。または、Unisysコンピュータ(9ビットバイト)またはTexas Instrumentsデジタルシグナルプロセッサ(16ビットバイト)をサポートする予定がない限り、8を使用してください。

void Bitset::assign(const string value) {
    int i, offset;

    if (bitset != NULL) {
        delete[] bitset;
    }

(11)のチェックNULLは不要です。

    bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];

(12)すでに述べたように、sizeof(char)定義上は1です。

(13)除算には整数の引数があるため、浮動小数点除算ではなく整数除算もあります。おそらくあなたが欲しいのはトリック(a+b-1)/bですか?

    for (i = 0; i < value.length(); i++) {

(14)スタイル:変数を最初の使用にできるだけ近いものとして宣言します。iここでは、次のように、ループヘッドでループカウンターを直接宣言することを意味しますfor( int i = 0, ...

        offset = (int) i/sizeof(unsigned char);

(14)そして同上offset。ただし、この変数の場合、値を変更する予定はないので、宣言しconstます。

        if (value[i] == '1') {
            bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
        } else {
            bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
        }

(15)それらのシフト操作をよりよく考え直してください!

    }

    set_size = value.length();
}

乾杯&hth。、

于 2010-11-16T05:02:25.060 に答える
0

割り当てサイズがゼロでないことを確認してください。これがここで起こっていることであり、割り当てられていないガベージメモリに書き込んでいるだけだと思います。valgrind の下で実行すると、これもキャッチされます。

于 2010-11-16T02:48:56.883 に答える