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;

然后,我调用 reset 方法,它执行 m_histogram = Histogram(512, 512, 3) - 新对象通过 new 初始化了 m_buffer。

所以预期的日志消息序列是:

  • “重置()调用:缓冲区:0x0”
  • “析构函数:缓冲区:0x0”

但相反,我得到:

  • “重置()调用:缓冲区:0x0”
  • “析构函数:缓冲区:0x072a7de”

因此正在执行一些非理性的操作。此外,当我还删除第二个对象(使用“更大”构造函数创建,具有三个 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;

其次,更重要的是,既然你已经动态分配了内存,你应该遵循三个规则,实现一个复制构造函数和赋值运算符,以及修复析构函数。

现在发生的事情是您的(编译器合成的)赋值运算符正在制作“浅”副本,即它正在复制指针。然后你会有多个析构函数试图删除它。您正在调用未定义的行为。

std::vector<uint8>通过使用 a作为缓冲区,你真的可以为自己省去很多麻烦。

于 2012-07-20T06:54:15.070 回答