0

私は単純なクラスを持っています:

class Histogram {
    int m_width;
    int m_height;
    int m_sampleSize;
    int m_bufferWidth;
    int m_bufferHeight;

    uint8* m_buffer;
    int m_size;
public:
    Histogram() : m_buffer(0) { }
    Histogram(int width, int height, int sampleSize) {
        m_buffer = new unsigned char [width*height*sampleSize];
    }
    ~Histogram() {
        my_log("destructor: buffer: %p", m_buffer);
        if ( m_buffer ) { delete [] m_buffer; m_buffer = NULL; }
    }
    unsigned char* buffer() {
        return m_buffer;
    }
};

それは他のクラスのメンバーです:

class Other {
    Histogram m_histogram;

    void reset() {
        my_log("reset() called: buffer: %p", m_histogram.buffer());
        m_histogram = Histogram(512, 512, 2);
    }
}

ここで、最初に Histogram() コンストラクター (m_buffer を NULL に設定) を使用して「初期化されていない」オブジェクトを作成します。

次に、m_histogram = Histogram( 512, 512, 3 ) を実行する reset メソッドを呼び出します。新しいオブジェクトには、new によって初期化された m_buffer があります。

したがって、予想されるログ メッセージの順序は次のとおりです。

  • 「reset() が呼び出されました: バッファ: 0x0」
  • 「デストラクタ: バッファ: 0x0」

しかし、代わりに、私は得る:

  • 「reset() が呼び出されました: バッファ: 0x0」
  • 「デストラクタ: バッファ: 0x072a7de」

したがって、いくつかの不合理な行動が実行されています。さらに、2 番目のオブジェクト (3 つの int パラメータを持つ「より大きな」コンストラクタで作成) も削除すると、アドレス 0x072a7de が表示されます。

4

2 に答える 2

2

クラス Histogram の copy-ctor と代入演算子を実現する必要があります。

m_histogram = Histogram(512, 512, 2);

代入演算子呼び出しです。暗黙の演算子 = クラスのビットごとのコピー メンバー。

また、配列を割り当てるため、delete[]ではなくデストラクタで使用する必要があります。delete

于 2012-07-20T06:56:04.300 に答える
1

まず、動的に割り当てられた配列を指しているため、演算子を使用する必要がありますdelete[]

delete[] m_buffer;

2 つ目は、さらに重要なことですが、メモリを動的に割り当てているため、3 つのルールに従って、コピー コンストラクターと代入演算子を実装し、デストラクタを修正する必要があります。

ここで何が起こるかというと、(コンパイラで合成された) 代入演算子が「浅い」コピーを作成している、つまりポインタをコピーしているということです。次に、それを削除しようとする複数のデストラクタがあります。未定義の動作を呼び出しています。

std::vector<uint8>をバッファとして使用することで、多くの問題を解決できます。

于 2012-07-20T06:54:15.070 に答える