I am trying to allocate memory on the heap for an array at object creation in my custom constructor. The array's size is determined by previously initialized instance variables. Here's my code for clarity.
struct PNG {
PNG() = delete;
PNG(unsigned width, unsigned height):
d_width(width),
d_height(height),
d_imageData(new unsigned int [d_width * d_height])
{
};
PNG(PNG const &);
PNG & operator = (PNG & other);
friend std::ostream & operator << (std::ostream & os, PNG & png);
unsigned d_width;
unsigned d_height;
unsigned d_imageData; // unsigned d_imageData []; has the same issue
};
This code gives me the error:
error: cannot initialize a member subobject of type 'unsigned int' with an rvalue of
type 'unsigned int *'
d_imageData(new unsigned int [d_width * d_height])
I am confused by two things:
lvalue
and not an rvalue
which wouldn't
have storage. d_width
, d_height
accessible after their own mention in the initialization list?I had seen it done this way but wanted to try the initialization list. Now, I am learning something new by playing with the code. Is this the only way that is possible?
PNG(unsigned int width, unsigned int height) {
width_ = width;
height_ = height;
imageData_ = new HSLAPixel[width * height];
}
This question comes close but it uses std::initializer_list
which I am not trying to use and I am not going to need templates as suggested in the accepted answer. More importantly, the array values would be filled out later and not at object construction.
Your constructor is fine. But since you are allocating memory for d_imageData
using new[]
, you need to declare d_imageData
as a pointer type, not an integer type, eg:
unsigned int *d_imageData; // <-- notice the *
(and don't forget to include a destructor that calls delete[] d_imageData;
- see the Rule of 3/5/0).
And yes, you can use d_width
and d_height
in the call to new[]
in your constructor's member initializer list, since they are declared before d_imageData
in of the declaration of PNG
, and thus are initialized before d_imageData
.