2D array as return value c++ - c++

I want to build a function which returns a 2D array
TExposureType** CAteImage::GetExposureMatrix()
{
TExposureType** ptr = new TExposureType*[FORMAT_MATRIX_ROWS];
for (int i = 0; i < FORMAT_MATRIX_ROWS; i++)
{
ptr[i] = new TExposureType[FORMAT_MATRIX_COLS];
for (int j = 0; j < FORMAT_MATRIX_COLS; j++)
{
ptr[i][j] = m_ExposureMatrix[i][j];
}
}
return ptr;
}
I know my code isn't effective - i can do the same with with a single malloc + 1 memcpy.
I can't however figure how to return the member i have m_ExposureMatrix[i][j] as a const ref?
TExposureType m_ExposureMatrix[FORMAT_MATRIX_COLS][FORMAT_MATRIX_ROWS];

if I understand your question correctly, (and that's a big if), this is what you want:
In your class header:
const TExposureType (&GetExposureMatrix()) [FORMAT_MATRIX_COLS][FORMAT_MATRIX_ROWS];
and in your cpp file
const TExposureType (&CAteImage::GetExposureMatrix()) [FORMAT_MATRIX_COLS][FORMAT_MATRIX_ROWS]
{
return m_ExposureMatrix;
};
You can significantly shorten this up with decltype if you have a compliant compiler that supports it, btw. Either way, you should be able to return m_ExposureMatrix by const-reference doing the above.

Related

Allocating pointer to a pointer

I have 5 buffers and 20 frames to write in them. Being one frame per buffer, at a certain moment i will have to overwrite buffers with the newest frame.
At random moments i need to read the oldest frame(its id and data) from all the buffers.
I am obliged to use a pointer to a pointer for my buffers, but since i suck at pointers, not even the allocation works, giving me a SEGMENTATION FAULT and not sure why.
What i have until now:
void fakeFrame(uint16_t *data)
{
for (auto i = 0; i < 1440; i++)
for (auto j = 0; j < 1440; j++)
data[(i * 1440) + j] = std::rand()%2;
}
int main()
{
uint16_t **p_frameBuffers;
uint32_t *p_frameIdxs;
uint16_t wrIdx = 0;
uint16_t reIdx = 0;
uint16_t currentFrameCounter = 0;
uint16_t nbBuffers = 5;
for(auto i =0; i< nbBuffers; i++)
{
p_frameBuffers[i] = (uint16_t*)malloc(1440*1440*2);
}
while(currentFrameCounter <= 20)
{
wrIdx++;
wrIdx %= nbBuffers;
if(wrIdx == reIdx)
{
std::cout<<"i passed the limit";
}
currentFrameCounter++;
p_frameIdxs[wrIdx] = currentFrameCounter;
fakeFrame(p_frameBuffers[wrIdx]);
}
std::cout<<"\n";
return 0;
}
I can see a few different problems with this code here.
You declare the long-form of the function for fakeFrame() in the beginning of the program, when the standard is usually to declare the function header first.
This is like a warning to the program that a function is about to be used, and that it's not part of a class or anything. Just standalone.
Example:
#include <iostream>
void fakeFrame();
int main()
{
return 0;
}
void fakeFrame()
{
for (auto i = 0; i < 1440; i++)
for (auto j = 0; j < 1440; j++)
data[(i * 1440) + j] = std::rand()%2;
}
You're also using some of these 16 and 32 bit unsigned ints as if they were arrays, so I was deeply confused about that. Did you mean to set them as arrays?
You also have some variables being declared in a non-array context but being used as arrays. I'm not deeply familiar with the uint variable/object types but I know they aren't usually meant to function as standalone arrays.
Also, no variable called m_pFrameBuffers is actually declared in the code you provided. Plus this is also used as an array, so it should really be declared as one.
I hope this provides at least some insight into what's not working. I'm actually kind of surprised that the void function ran before, it's improperly formatted.
In the end this is what did it: the pointer to a pointer is actually an array of pointers (which i did not know, of course)
p_frameBuffers = (uint16_t**)malloc((sizeof(uint16_t*)*nbBuffers));
for(auto i = 0; i < nbBuffers; i++)
{
p_frameBuffers[i] = (uint16_t*)malloc(1440*1440*2);
}

Trying to copy a 2D dimensional array of objects to another function

I'm trying to copy an array from one class to to another class by passing it to a function but I'm running into issues. The array that I'm trying to copy seems to lose all its data.
// A.h
class A
public:
virtual void Test();
private:
A* array2D[30][32];
// A.cpp
void A::Test()
{
B* f = new B();
f->pass(array2D);
}
// B.h
class A;
class B
{
public:
void pass(A *a[][32]);
private:
A *a[30][32];
}
// B.cpp
void B::pass(A *array2D[][32])
{
for (int i = 0; i <= 30; i++)
{
for (int j = 0; j <= 32; j++)
{
a[i][j] = array2D[i][j];
}
}
}
My guess is that it's happening when I'm passing it but I'm not sure what I'm doing wrong.
My guess is that it's happening when I'm passing it but I'm not sure what I'm doing wrong.
First, your for loops to populate the array go out-of-bounds on the last iteration of the nested for loop:
void B::pass(A *array2D[][32])
{
for (int i = 0; i <= 30; i++) // This goes out-of-bounds on the last iteration
{
for (int j = 0; j <= 32; j++) // This also goes out-of-bounds.
{
a[i][j] = array2D[i][j];
}
}
}
Using <= in a for loop is an indication that things can go wrong, and they do go wrong with your code. The fix would simply be:
void B::pass(A *array2D[][32])
{
for (int i = 0; i < 30; i++)
{
for (int j = 0; j < 32; j++)
{
a[i][j] = array2D[i][j];
}
}
}
This will work, however it is inefficient (unless a great optimizing compiler sees that this is inefficient and changes the code).
The better way to do this is a simple call to std::copy:
#include <algorithm>
void B::pass(A *array2D[][32])
{
std::copy(&array2D[0][0], &array2D[29][32], &a[0][0]);
}
The reason why this works is that two-dimensional arrays in C++ have their data layout in contiguous memory, thus it is essentially a one-dimensional array. So giving the starting and ending address of the array elements is all that's required.
A compiler will more than likely see that you are copying a trivially-copyable type (a pointer), thus the call to std::copy results in a call to memcpy.

How to correctly pass an 2D array pointer as argument?

For the heads up: I am incredibly new with cpp. Being used to PHP and JS as work languages, I find pointers incredibly confusing.
So I have this Class called Macierz. The class is supposed to hold Matrixes of float variables and ought to have a constructor accepting an 2d array in order to print them into the field.
The field is declared like this
float mx3[3][3];
And the constructor has such declaration: Macierz(float**);
With the body using an additional function:
Macierz::Macierz(float** f) {
length = 3;
populateWith(f, length);
}
void Macierz::populateWith(float** val, int length) {
for (int i = 0; i < length; i++)
for (int j = 0; j < length; j++)
mx3[i][j] = val[i][j];
}
In my main() function I want to declare the class with a created float array.
I try to do it as so, but It just won't work the way God intended:
float y[3][3] = { {1.00f, 2.00f, 3.00f}, { 4.00f, 5.00f, 6.00f }, { 7.00f, 8.00f, 9.00f } };
Macierz m5(y);
This is the base template of what I want to do. I've tried making the y variable a double pointer, a regular pointer, passing via reference and it just won't kick.
What would be the most prober way to pass this variable?
Any help will be amazing, I am really a noob in this language.
You need to remember that arrays naturally decays to pointers to their first element. But that isn't recursive.
For y in your example, the decay is to a pointer to the first element of y, which is equal to &y[0]. That is a pointer to an array, and will have the type float(*)[3], which is the type you need for your arguments:
Macierz::Macierz(float (*f)[3]) { ... }
Managed to fix this by copying the float into a pointer-to-pointer types
float y[3][3] = { {1.00f, 2.00f, 3.00f}, { 4.00f, 5.00f, 6.00f }, { 7.00f, 8.00f, 9.00f } };
float** x = 0;
x = new float*[3];
for (int i = 0; i < 3; i++) {
x[i] = new float[3];
for (int j = 0; j < 3; j++) {
x[i][j] = y[i][j];
}
}
Macierz m5(x);

C++ : Changing the value of a fixed-sized 3D array in a function

I have a stack-allocated fixed-sized 3D array declared as such:
ofVec2f geometry[24][30][4];
I need to pass this to a function to updates all the ofVec2f values, with a procedure along the lines of...
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 30; j++) {
ofVec2f verts[4];
for (int k = 0; k < 4; k++) {
verts[k] = foo;
}
geometry[i][j] = verts;
}
}
My question is, how do I pass this data structure to a function to update these values and have the array point to this new array of ofVec2f values? I imagine I will need to pass them via pointers but I'm not sure how to do it, especially since I have a fixed array on the stack.
Thanks! let me know if you need to see anything else.
You can do it:
1) By reference:
void function(ofVec2f (&array)[24][30][4]);
2) By pointer:
void function(ofVec2f (*array)[30][4]);
3) Using templates, to pass array of any size:
template <size_t X, size_t Y, size_t Z>
void function(ofVec2f (&array)[X][Y][Z]);
You can pass it by reference or pointer. If, like me, you find the syntax for reference-to-array a bit toxic you might like to use a using alias or a typedef:
using GeometryType = ofVec2f[24][30][4]; // C++11
//typedef ofVec2f GeometryType[24][30][4]; // C++98
void fillGeometry(GeometryType& geometry) {
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 30; j++) {
for (int k = 0; k < 4; k++) {
geometry[i][j][k].setX(0.0);
}
}
}
}
Have you kept a reference to the old arrays anywhere? If not, why are you creating a new set of arrays and then pointing to them (and thus marking the old arrays for garbage collection)? Why not just assign the new values to the existing arrays?
for (int k = 0; k < 4; k++) { (and thus
geometry[i][j][k] = foo;
}

Aliasing vector correctly

I have not been able to find the answer elsewhere, so I guess I just have to ask this one: I am trying to get an alias for a vector (in which int pointers are stored), as below:
void conversion(Engine * ENGINES)
{//The Engine class has a vector of int* as a public data member called SITE
for (int i = 0; i < 3; i++)
{
vector <int*>* current = &(ENGINES[i].SITE);//the problematic line
int j_max = current -> size();
cout << j_max << endl;
for (int j = 0; j < j_max; j++)
{
for (int k = 0; k < 3; k++)
{
if (*current[j][k] == 2)
*current[j][k] = 1;
if (*current[j][k] == -1)
*current[j][k] = 0;
}
}
}
}
The problem is that there seems to be an inversion of the indices for the *current[a][b]. I want to be able to use current as a normal vector, but now the indexing is reversed compared to:
vector <int*> current1 = ENGINES[1].SITE;
so that *current[i][j] = current1[j][i] for some reason. Is there a mistake in my syntax?
I believe your problem is that [] has higher precedence than unary *. So you're getting *(current[j][k]) instead of (*current)[j][k], which is what you want.
However you could eliminate that problem by just taking a reference rather than a pointer:
vector <int*>& current = (ENGINES[i].SITE); and then just remove your extra loading * operators on access to current.
The problem is that [] has greater precedence than * (dereference), so *current[i][j] is interpreted as *(current[i][j]), which is probably not what you want.
Actually, this idiom of aliasing is commonly expressed as a reference, not a pointer:
vector <int*>& current = ENGINES[i].SITE;
and use simply current[i][j].
As I suspected in my comment, use a reference.
vector <int*> &current = ENGINES[i].SITE;