创建对象后丢失的缓冲区内容

float type Buffer contents lost after creating object C++

本文关键字:缓冲区 创建对象      更新时间:2023-10-16

我有一个类,它包含一个浮点类型缓冲区,指向一个RGB值数组。缓冲区被创建并正确存储,但是当我通过一个函数返回该类的实例到main()时,缓冲区的内存是不可读的。下面是初始类:

namespace imaging
{
    typedef float component_t;
    class Image
    {
        protected:
            component_t * buffer;
            unsigned int width, height;
        public:
            Image(unsigned int width, unsigned int height, const component_t * data_ptr) {
            this->width = width;
            this->height = height;
            this->setData(data_ptr);
            this->buffer = const_cast<component_t *>(data_ptr);
        }
        component_t getRedValPixel(unsigned int x, unsigned int y) const {
            int pos = x * this->width * 3;
            component_t red;
            red = this->buffer[pos];
            return r;
        }
    }
}

要创建该类的实例,我使用readImage(char* filepath)方法,该方法在加载数据后具有返回语句:

return &Image(width, height, buffer);
下面是main()函数中的代码:
Image* image = readIamge(filepath);
int width = image->getWidth(); //retrieves it correctly
int height = image->getHeight(); //retrieves it correctly
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        cout << image->getRedValPixel(i,j);
    }
}

让我们仔细看看你的返回语句:

return &Image(width, height, buffer);

执行Image(...)时,会创建一个临时对象。一旦它所在的表达式结束,这个临时对象将被销毁。然后你返回一个指向这个临时对象的指针,这个对象很快就会消失,给你留下一个指向不存在对象的指针。试图对该指针解引用将导致未定义行为

从文件读取的数据可能仍在内存中的某个地方,但从返回的指针中不可用。

我建议你通过值返回对象,并学习像移动语义移动构造函数和3,5和0的规则。我还建议您不仅复制指向对象实际数据的指针,还要复制实际数据本身(深度复制)。

return &将返回堆栈中本地创建的对象的地址,该对象将在失去作用域(即返回语句)后立即销毁。

解决方案是在堆中分配Image对象。例如

main()
{
....
Image* image = NULL;
readImage(filepath, image );
int width = image->getWidth(); //retrieves it correctly
int height = image->getHeight(); //retrieves it correctly
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        cout << image->getRedValPixel(i,j);
    }
}
delete image;
image = NULL
...
}

void readImage(char* filepath, Image* o_pBuffer ) 
{
   .....
   o_pBuffer = new Image(width, height, buffer);
   return o_pBuffer;
}

main()
{
....
Image* image = NULL;
image = readImage(filepath );
int width = image->getWidth(); //retrieves it correctly
int height = image->getHeight(); //retrieves it correctly
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        cout << image->getRedValPixel(i,j);
    }
}
delete image;
image = NULL
...
}

Image* readImage(char* filepath ) 
{
   .....
   Image* o_pBuffer = new Image(width, height, buffer);
   return o_pBuffer;
}