Question

I have a class for loading and storing (then deleting) image data (pixel and headers). In the constructor I initialize the data and bitmap headers like this:

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

and data is an unsigned char* array allocated with new[...] in load function. The destructor:

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

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

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

Now the problem is that in the filtering class, I pass the class object after loaded the data as a parameter:

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

This is a shortened version of my code. So, the IMAGE_DATA ::load runs smooth, but when the code arrives at the scaling function, I get the following assertion failure:

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

in crt\src\dbgdel.cpp at line 52.

This happens since I made the destructor. For curiosity I changed the paramters so I pass them as reference.

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

And this works now. If I pass 'by value', it seems like the destructor is called, but constructor should also, and there should be no problem since in the constructor I initialize everything.

I want to pass it by value, because I want to left the original unchanged, I just want to use it's data.

How can I make it work without passing as reference and how it is different from passing by value, since by value seems more 'safe'.

EDIT: I've just found a post about this: Side effects when passing objects to function in C++ (I've not searched with the right keywords it seems) So from this post I've read I should make a copy constructor, and an assignment operator.

Was it helpful?

Solution

In C++, there is a 'rule of threes', which basically states, if you have a custom destructor, you also should most probably create a copy constructor and a copy assignment operator.

You are right in assuming that a constructor gets called when you 'pass by value' - however, that is the copy constructor, not the default constructor that you provided.

If you do not define one, the compiler will happily provide one for you - but it will do a 'shallow' copy of all the pointers that you have - essentially, your copy will point to the same memory as the original. I guess you can understand why then it deletes your original :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top