Assignment of objects to pointers

Good day, forumites. Since my c++ skills are very rusty, I managed to entangle myself in the following mess:

I am using OpenCV to read and manipulate a set of images, which I need to store in an array to work with them. Here is a snippet of the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define MAX_IMAGES 8

typedef Mat* MatPtr;

int main(int argc, char** argv) {
  char imageName[] = "./res/imageX.tiff";
  MatPtr datacube[MAX_IMAGES];

  for(unsigned int i = 0; i < MAX_IMAGES; i++) {
    imageName[11] = 49 + i;
    *datacube[i] = imread(imageName, -1);
  }

  return 0;
}


As you can see, I have an array of pointers to Mat objects (an OpenCV class used to hold info and data about an image), which I will use to store the images. The function imread reads an image and returns a Mat object loaded with the relevant data about the image.

However, this gives me a nice segfault when the assignment takes place. Of course, I can swap it with the following code, but since I'm working with big images (2048x2048 and upwards), it's really inefficient:

1
2
3
4
  for(unsigned int i = 0; i < MAX_IMAGES; i++) {
    imageName[11] = 49 + i;
    datacube[i] = new Mat(imread(imageName, -1));
  }


Is there any way to do this elegantly and without much hassle?

Again, excuse my rustiness and anything completely stupid I might have said. It's been a long time since I worked with C++.

-- EDIT --

Managed to circumvent the problem by using a STD vector instead of an array. I'd still like to know the answer to this riddle...
Last edited on
> However, this gives me a nice segfault when the assignment takes place
yes, you are dereferencing invalid pointers (they are uninitialized)
¿why are you using pointers in the first place?
1
2
3
4
Mat datacube[MAX_IMAGES];

//...
datacube[K] = imread(imageName, -1);
IIRC opencv makes shallow copies with reference counting, so the assignment is quite cheap.
i think the problem is that datacube[i] is just a pointer not pointing to any memory address. if you try to dereference it, it will throw an error.

You will have to allocate a new address as done in the second option that you presented. Or as you rightly pointed out, you can use vectors.

EDIT: Why are you using pointers at all? why can't you simply
Mat datacube[MAX_IMAGES];

EDIT 2: oops sorry ne555
Last edited on
What exactly does the imread return? A Mat by value?

Lets simplify your first version:
1
2
3
Mat image; // equivalent to return from imread()
Mat * ptr[1];
*ptr[0] = image;

A copy assignment to memory location pointed to by ptr. Alas, ptr does not point anywhere. Crash.

Your second version:
1
2
3
Mat image;
Mat * ptr[1];
ptr[0] = new Mat( image );


The std::vector;
1
2
3
Mat image;
vector<Mat> data(1);
data[0] = image;

which is equivalent to:
1
2
3
Mat image;
Mat * data = new Mat[1];
data[0] = image;


Why do you think that your second version is inefficient? What might it imply, that the imread returns Mat by value?
@ne555 @abhishekm71

1
2
3
4
Mat datacube[MAX_IMAGES];

//...
datacube[K] = imread(imageName, -1);


Doesn't that construct MAX_IMAGES Mat objects with the default constructor before I assign them the real object?

@keskiverto

Using a copy constructor for images with a size of 8 MB each doesn't look good to me...

I simply want to assign the memory address to the pointer, but it complains that the object in question is temporal and will be destroyed.


But really, I think Java really eroded my knowledge of c++...
What does the Mat contain? At least two size_t and one pointer? Default constructor of such is bound to be cheap. If it indeed uses shallow copies, then copy ctor is cheap too. imread would return a pointer, if copying would be expensive.
Doesn't that construct MAX_IMAGES Mat objects with the default constructor before I assign them the real object?


yes it does. Ref: http://www.parashift.com/c++-faq/arrays-call-default-ctor.html

Do you want all the 8 Mat objects available to you at any future time in the program? Or do you want to construct a Mat object, then destroy it and then construct another one?

For the former scenario, I don't know of any method in which you shall be able to save on memory.

For the latter case, one solution is don't use arrays. Just keep one variable object and keep over-writing it.
Topic archived. No new replies allowed.