c++ - 在析构函数中删除[]并将类对象传递给函数作为参数

标签 c++ memory-management c++11 destructor pass-by-value

我有一个用于加载和存储(然后删除)图像数据(像素和标题)的类。在构造函数中,我像这样初始化数据和位图 header :

IMAGE_DATA::IMAGE_DATA():data(0)
{
    memset(&fileheader,0,(sizeof(BITMAPFILEHEADER)));
    memset(&infoheader,0,(sizeof(BITMAPINFOHEADER)));
};

data 是一个 unsigned char* 数组,在 load 函数中用 new[...] 分配。 析构函数:

IMAGE_DATA::~IMAGE_DATA()
{
    freeData();
};

void IMAGE_DATA::freeData()
{
    delete[] data;

    memset (&fileheader, 0, sizeof(fileheader));
    memset (&infoheader, 0, sizeof(infoheader));
};

现在的问题是,在过滤类中,我将加载数据后的类对象作为参数传递:

IMAGE_DATA image;

image.load("filename"); //load headers and pixel data

FILTER filter;

filter.scale(image,scalefactor,"outputfilename");  //scales the image and write to a .bmp

这是我的代码的简化版本。因此,IMAGE_DATA::load 运行顺利,但是当代码到达缩放函数时,我得到以下断言失败:

Debug Assertion Failed!
....
Expression:
_BLOCK_TYPE_IS_VALID(pHeap->nBlockUse)
....

crt\src\dbgdel.cpp 的第 52 行。

这是在我创建析构函数后发生的。出于好奇,我更改了参数,因此将它们作为引用传递。

/*FILTER::*/scale(IMAGE_DATA& /*passed as reference*/, unsigned short, const char*); 

现在可以了。如果我“按值”传递,似乎调用了析构函数,但也应该调用构造函数,而且应该没有问题,因为在构造函数中我初始化了所有内容。

我想按值传递它,因为我想保持原来不变,我只想使用它的数据。

如何在不作为引用传递的情况下使其工作,以及它与按值传递有何不同,因为按值传递似乎更“安全”。

编辑: 我刚找到一篇关于此的帖子:Side effects when passing objects to function in C++ (我似乎没有使用正确的关键字进行搜索)所以从这篇文章中我读到我应该制作一个复制构造函数和一个赋值运算符。

最佳答案

在 C++ 中,有一个“三分法则”,它基本上规定,如果您有一个自定义析构函数,您很可能还应该创建一个复制构造函数和一个复制赋值运算符。

您假设在“按值传递”时调用构造函数是正确的 - 但是,这是复制构造函数,而不是您提供的默认构造函数。

如果您不定义一个,编译器会很乐意为您提供一个 - 但它会为您拥有的所有指针做一个“浅”拷贝 - 本质上,您的拷贝将指向与原始指针相同的内存。我想你能理解为什么它会删除你原来的:)

关于c++ - 在析构函数中删除[]并将类对象传递给函数作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20529929/

相关文章:

c++ - 如何检查成员函数是否有 const 重载?

C++11 兼容的线性分配器实现

java - Java中方法的内存分配

c++ - 为什么 putchar ('\\\' );不会工作

c++ - 我们的程序可以在编译时确定它正在被哪个编译器编译吗?

c++ - 如何在不使用 time_t 的情况下将 std::chrono::time_point 转换为 std::tm?

c++ - 使用 pugixml 为不同的输入映射节点名称

c++ - 寻求对内联命名空间的澄清

c++ - 为什么 const_iterator 不像 reverse_iterator 那样提供基类?

c++ - 我如何在这里使用 placement new ?