I have to write a constructor for implementing a function for initializing an internally allocated matrix. The given code looks like (only constructor):
Matrix(const float* m, size_t n) : _n(n), _m(0lu)
{
//Missing
}
So, my first question is: What does the part behind the ':' mean (_n(n), _m(0lu))?
Furthermore, as far as I know, I need a return pointer to the memory I am allocating. Is this correct? My first idea was to use posix_memalign(...). Would this be correct?
Thank you very much!
I am assuming this basic object:
class Matrix
{
// stuff
private:
size_t _n;
float* _m;
}
The part of the constructor is an initialization list. It is synonymous to wiring:
Matrix(const float* m, size_t n)
{
_n = n;
_m = 0lu;
}
Here is a good decription, why you want to use them: [10.6] Should my constructors use "initialization lists" or "assignment"?
But that does not solve your initial problem: "function for initializing an internally allocated matrix"
What the constructor does is copy the size (n) and initialize the pointer to NULL. (NULL is synonymous with 0 [1]) So you need some way to internally allocate and initialize.
I have one problem with the Matrix class. Normally a matrix has 2 dimension, so either it is a NxN matrix or n is the element count and we have no idea what dimension the matrix is. I will assume that it is NxN matrix, since this is quite often used in computer graphics.
Step 1: internally allocated
So, allocate some memory:
_m = new float[n*n];
This can replace the assignment to NULL, since why should it be first set to NULL and then change right after.
Step2: initialized
Assuming that the calling code put sufficient data into m, just use memcpy:
std::memcpy(_m, m, n*n*sizeof(float));
If you feel masochistic, you can also copy the elements each:
for (unsigned int i = 0; i < n*n; i++)
{
_m[i] = m[i];
}
So your final constructor looks like so:
#include <cstring>
Matrix(const float* m, size_t n)
: _n(n), _m(new float[n*n])
{
std::memcpy(_m, m, n*n*sizeof(float));
}
Finally, since you allocated memory you should not forget to delete it in the destructor:
Matrix::~Matrix()
{
delete [] _m;
}
Note the array deleting operator.
[1] In C++11 and C99 this is not fully true under certain circumstances, but these are details and irrelevant.
:_n(n), _m(0lu)
is member internalizer list. Means _n(which seems to be member variable) is assing n to it and simialr for _m
More details here
Related
Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;
I am trying to implement matrix multiplication in c++. I found a sample code using a class that writes in .h and .cpp files. This is just a part of the code that related to my question:
#include "Matrix.h"
// Constructor - using an initialisation list here
Matrix::Matrix(int rows, int cols, bool preallocate): rows(rows), cols(cols), size_of_values(rows * cols), preallocated(preallocate)
{
// If we want to handle memory ourselves
if (this->preallocated)
{
// Must remember to delete this in the destructor
this->values = new double[size_of_values];
}
}
void Matrix::matMatMult(Matrix& mat_left, Matrix& output)
{
// The output hasn't been preallocated, so we are going to do that
output.values = new double[this->rows * mat_left.cols];
// Set values to zero before hand
for (int i = 0; i < output.size_of_values; i++)
{
output.values[i] = 0;
}
I wonder why they initialised using the output matrix with 0s output.values[i] = 0; while it has been allocated memory before?
From cppreference on new expression:
The object created by a new-expression is initialized according to the following rules:
[...]
If type is an array type, an array of objects is initialized.
If initializer is absent, each element is default-initialized
If initializer is an empty pair of parentheses, each element is value-initialized.
"default-initialized" ints are colloquially not initialized. They have indeterminate values. The empty pair of parantheses refers to what Ted mentioned in a comment:
output.values = new double[this->rows * mat_left.cols]{};
Value initialization is described here. The case that applies here is
otherwise, the object is zero-initialized.
I wonder why they initialised using the output matrix with 0s output.values[i] = 0; while it has been allocated memory before?
Allocating memory and initializing an object are two seperate steps. Yes, the elements have to be initialzed, allocating memory is not sufficient.
ok so suppose I have a function myFunction. Then in main i have a multi dimensional array of pointers. I want to pass a pointer to this array of pointers into myFunction. How would I do that? I know that If you want to pass an int to my function, one can write the function as
myfunct( int x) { ...}
What would that type of x be if I have to pass a pointer to an array of pointers? Thanks in advance :D
Typically you want to modify the elements of an array rather then the actual pointer. The actual pointer is given by malloc and if you change it, by writing directly to the value, it won't affect the memory allocation (except you might loose the initial pointer...).
This might be what you're looking for in a 2D array.
void myfunct(int** ptr,int items, int array_items)
{
//some code
}
int main(int argc, char *argv[])
{
const auto items = 5;
const auto array_items = 7;
int** multi_dimensional_array = reinterpret_cast<int**>(std::malloc(items * sizeof(int*)));
for (auto i = 0 ;i < items;++i)
{
multi_dimensional_array[i] = static_cast<int*>(std::malloc(sizeof(int) * array_items));
}
myfunct(multi_dimensional_array,items,array_items);
//deallocate
}
Wrap your multidimensional array inside a class. That way you can carry the data and dimensions in one block and passing it around is as simple as moving around any other class.
Remember to observe the Rules of Three, Five, and Zero, whichever best applies to how you store your array inside your class. std::vector is a personal favourite because it allows you to use the Rule of Zero.
For example:
#include <iostream>
#include <vector>
struct unspecified
{
};
template<class TYPE>
class TwoDee{
int rows;
int cols;
std::vector<TYPE> data;
public:
TwoDee(int row, int col):rows(row), cols(col), data(rows*cols)
{
// does nothing. All of the heavy lifting was in the initializer
}
// std::vector eliminates the need for destructor, assignment operators, and copy
//and move constructors. All hail the Rule of Zero!
//add a convenience method for easy access to the vector
TYPE & operator()(size_t row, size_t col)
{
return data[row*cols+col];
}
TYPE operator()(size_t row, size_t col) const
{
return data[row*cols+col];
}
};
void function(TwoDee<unspecified *> & matrix)
{
// does stuff to matrix
}
int main()
{
TwoDee<unspecified *> test(10,10);
function(test);
}
To directly answer your question, typically the type passed will be int * for a vector of int, and int ** for a 2D array of int
void myfunct( int **x)
{
x[2][1] = 25;
return;
}
If for some reason you wanted that to be an array of int pointers instead of int you need an extra *.
void myfunct( int ***x)
{
*(x[2][1]) = 25;
return;
}
Let me first try to interpret the exact type that you want to deal with. I suppose in your main function there is a "multidimensional array" which stores pointers for each element. As an example, let's say you have a 3-dimensional array of pointer to integer type.
Assume that you know the size of the array:
C style array will look like this:
int *a[4][3][2];
that means a is a 4x3x2 array, and each element in the array is a pointer to integer. So overall you now have 24 pointers to integer in total, as can be seen by testing the result of sizeof(a) / sizeof(int*) (the result should be 24). Okay, so far so good. But now I guess what you want is a pointer to the array a mentioned above, say b, so b is defined
int *(*b)[4][3][2] = &a;
Notice that although now b looks intimidating, in the end it is just a pointer which just stores an address, and sizeof(b) / sizeof(int*) gives 1 as the result. (The * inside parenthesis indicates b is pointer type, so b is a pointer to a "multidimensional array" of pointers to integer.)
Now to pass b to myFunction, just give the same type of b as argument type in the declaration:
void myFunction(int *(*x)[4][3][2]) {
// do something
}
And that's it! You can directly use myFunction(b) to invoke this function. Also, you can test that inside myFunction, x is still of the size of one pointer, and *x is of the size of 24 pointers.
*Note that since we are passing a pointer to array type into the function, the array-to-pointer decay does not apply here.
Assume you don't know the size of the array at compile time:
Say you have int N1 = 4, N2 = 3, N3 = 2; and you want to initialize a N1xN2xN3 array of pointer to integer, you cannot directly do that on the stack.
You could initialize use new or malloc as suggested in #Mikhail's answer, but that approach takes nested loops for multidimensional arrays and you need to do nested loops again when freeing the memory. So as #user4581301 suggests, std::vector provides a good wrapper for dynamic size array, which do not need us to free the memory by ourselves. Yeah!
The desired array a can be written this way (still looks kind of ugly, but without explicit loops and bother of freeing memory)
std::vector<std::vector<std::vector<int*>>> a (N1,
std::vector<std::vector<int*>> (N2,
std::vector<int*> (N3)
)
);
Now, b (the pointer to a) can be written as
auto *b = &a;
You can now pass b with
void myFunction(std::vector<std::vector<std::vector<int*>>>* x) {
// do something
}
Notice that the * before x means x is a pointer.
I have created a dynamic matrix of class objects but i have made a big mess with handling the returned pointers.
My intention is to create a matrix of class Point( Int x,Int y) and later to use it in different ways in the program.
Everything is working but i can't figure out the returned pointers game between the functions.
class Point
{
private:
int x;
int y;
public:
Point(int x,int y);
void SetPoint(int x,int y);
};
In a second class I use a Point object as class member.
Init_Pallet() is used to Initialize the Matrix.
class Warehouse
{
private:
Robot r1,r2;
Point *Pallet_Matrix;
public:
Point* Init_Pallet();
};
This is the Init function
Point* Warehouse::Init_Pallet()
{
int rows =10,cols =10;
Point** Pallet_Matrix = new Point*[rows];
for (int i = 0; i < rows; i++)
Pallet_Matrix[i] = new Point[cols];
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; j++) //Pallet matrix Init, x point for robots amount in position and y for box amount
Pallet_Matrix[i][j].SetPoint(0,0);
return *Pallet_Matrix;
}
The Init function is called by WareHouse C'Tor (ignore the other vars)
Warehouse::Warehouse(Robot p_r1,Robot p_r2): r1(p_r1),r2(p_r2)
{
this->r1=p_r1;
this->r2=p_r2;
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
}
My question is: How do I return the address to the beginning of the matrix from the Init function to the C'Tor who called it?
And second question: how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix adress to the C'Tor.
Thank you in advance for all the help and your time.
You should just have Init_Pallet return a Point** and then do return Pallet_Matrix;. Currently you're copying one of the Point*s that you allocated out of the function, so the copy is no longer part of a contiguous array that you can index.
Don't forget to delete[] the dynamically arrays in your destructor.
However, you should much prefer to use the standard library containers like std::array or std::vector. Then you don't need to worry about the dynamic allocation yourself and no pointers to get in a mess with.
If I were doing it, I would just have:
class Warehouse
{
public:
Warehouse() : Pallet_Matrix() { }
private:
Robot r1,r2;
std::array<std::array<Point, 10>, 10> Pallet_Matrix;
};
And that's it. No init needed. No dynamic allocation. No assigning 0 to every element (if you give Point a default constructor that zero-initialises). Done.
How do I return the address to the beginning of the matrix from the Init function to the C'Tor?
In case you would really need just an address of first element, pretty straightforward would be:
return &Pallet_Matrix[0][0];
how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix address
Init_Pallet is a member function, which could simply work with the Pallet_Matrix member directly. Otherwise, the Init_Pallet function could actually return Point**, which should however make you feel that something's wrong with this code.
Better[1] solution would be:
Define the default constructor for Point:
class Point
{
public:
Point() : x(0), y(0){}
...
Use std::vectors instead of dynamically allocated arrays:
class Warehouse
{
private:
std::vector< std::vector<Point> > Pallet_Matrix;
and instead of:
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
you would simply use std::vector's constructor:
int rows = 10, cols = 10;
Pallet_Matrix = std::vector< std::vector<Point> >(rows, cols);
[1] Better = You don't want to handle the memory management on your own.
The problem is that the returned type of Init_Pallet() is wrong — its a row, not a matrix. And in the last line of Warehouse::Init_Pallet() you dereference the proper pointer to matrix obtaining the pointer to the first row of the matrix.
You need to write Point **Pallet_Matrix; in Warehouse, use Point** Warehouse::Init_Pallet() definition of Init_pallet(), and return Pallet_Matrix in the last line of Init_Pallet().
The notation Point *row means the row is "the array of points" or "the pointer to the beginning of the array of points". The notation Point **matrix means the matrix is "the array of pointers to the beginnings of the arrays of points" or "the pointer to the beginning of such an array".
First: are the dimensions really constant, or is this just an
artifact of your having simplified the code for posting? If
they are really constant, there's no need for dynamic
allocation: you can just write:
Point palletMatrix[10][10];
and be done with it. (If you have C++11, it's even better; you
can use std::array, and palletMatrix will have full object
semantics.)
If you do need dynamic indexes, the only reasonable way of
doing this is to write a simple matrix class, and use it:
class Matrix
{
int m_rows;
int m_columns;
std::vector<Point> m_data;
public:
Matrix( int rows, int columns )
: m_rows( rows )
, m_columns( columns )
, m_data( rows * columns, Point( 0, 0 ) )
{
}
Point& operator()( int i, int j )
{
return m_data[ i * m_columns + j ];
}
// ...
};
Trying to maintain a table of pointers to tables is not a good
solution: it's overly complex, it requires special handling to
ensure that each row has the same number of columns, and it
generally has poor performance (on modern machines, at least,
where locality is important and multiplication is cheap).
Note too that the actual data is in an std::vector. There are
practically no cases where a new[] is a good solution; if you
didn't have std::vector (and there was such a time), you'd
start by implementing it, or something similar. (And
std::vector does not use new[] either.)
EDIT:
One other thing: if you're putting Point in a matrix, you might
want to give it a default constructor; this often makes the code
simpler.
const int ROWS = 3;
const int COLUMNS = 4;
void fillArray(double a[ROWS][COLUMNS], double value);
void deleteArray(double a[ROWS][COLUMNS]);
int main () {
double a[ROWS][COLUMNS];
fillArray(a, 0);
deleteArray(a);
}
In C++, how do you delete (or fill with specific values) a static n-dimension array?
In C++ we generally do not use arrays. We use std::vector.
You can use memset or std::fill to fill the array with specific values.
BTW you can use delete on dynamically allocated arrays not on static ones.
memset( a, 0 ,ROWS * COLUMNS * sizeof( double ));
or
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(double), 0);
You can delete only an object created by new (and that object will be allocated in the heap). What do you mean by "deleting a static POD variable"? It has no sense:
1) It doesn't have any destructor to perform additional tasks before freeing the memory,
2) The stack memory will be "freed" as you exit the current block.
And to set it: either loop, either simple memset(a, 0, sizeof(a)); .
Also, the array in your example is not static.
std::vector is what is generally used for C++ arrays (especially when you're new at it). One of vector's constructors will fill it for you to:
std::vector<type> myVector(initialSize, defaultValue);
If you want multidimensional, you could do a vector of vectors, or boost::multi_array:
boost::multi_array<type, numberOfDimensions> myArray(boost::extents[firstSize][secondSize][thirdSize]);
In that case, you'll need to use the multiple-for-loops approach, because it doesn't seem to have a constructor that does that.
EDIT: Actually you can use std::vector to make a multidimensional array with default values:
std::vector<std::vector<double> > a(3, std::vector<double>(4, 0));
Where 3 is the number of rows, 4 is the number of columns and 0 is the default value.
What it's doing is create a vector of vectors with 3 rows, where the default value for each row is a vector with 4 zeroes.
Filling arrays in C++ is the same as filling them using C, namely nested for loops
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
a[i][j] = 0
Arrays aren't "deleted" but they can use free if they've been allocated on the heap (if they've been allocated on the stack within a function, this is unnecessary).
int i;
for (i = 0; i < ROWS; i++)
free(a[i]);
free(a);
Firstly, the code you posted seems confused. What is it that you think "deleteArray" is supposed to do? 'a' is an auto variable and therefore cannot be deleted or freed.
Secondly, wrap your array in a class. There is a nice one in the FAQ that you can start with, but it can be improved. The first improvement is to use a vector rather than newing a block of memory. Then std::fill can be used to fill the array.
Use std::fill
#include <algorithm>
And then your implementation is simply:
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(a[0][0], value);
You don't delete the array since it is stack allocated.