out of bound check for multidimensional arrays - c++

I am reading a book on Safe C++. Here, the author mentioned how to avoid out of bound array reading. Here, it is mentioned how we can avoid out of bound array reading for multi dimension arrays. Here author used operator() function as shown in following link instead of operator[] and gave following explanation.
https://github.com/vladimir-kushnir/SafeCPlusPlus/blob/master/scpp_matrix.hpp
Note here that to access multidimensional array, we either need to use multiple [] operators, such as matrix[i][j], or a single () operator, such as matrix(i,j).
The first approach can be achieved if we had the [] operator return a T* pointer to the zeroth element of i-th row. However, this denies us the diagnosis of a column index out of bounds, which defeats the purpose of catching bugs at run-time. We could, of course, create some template class that would include a smart reference to a row, return an instance of using the first operator([i]), and then use the bounds check in the second operator ([j]).
My question what does author mean by "create some template class that would include a smart reference to a row, return an instance of using the first operator([i]), and then use the bounds check in the second operator ([j])." ? Request to provide sample code how we can implement above logic in C++?
Thanks for your time and help.

The basic idea looks something like this:
#include <vector>
#include <iostream>
template <class T>
class matrix {
size_t cols;
size_t rows;
std::vector<T> data;
class row_proxy { // This class is the part the question really asked about
size_t row;
matrix &m;
public:
row_proxy(matrix &m, size_t row) : row(row), m(m) {}
T &operator[](size_t col) {
if (row >= m.rows || col >= m.cols) // Note: row & col are indices not array count
throw std::logic_error("Bad index");
return m.data[row * m.cols + col];
}
};
public:
matrix(size_t cols, size_t rows) : rows(rows), cols(cols), data(rows*cols) {}
row_proxy operator[](size_t row) {
return row_proxy(*this, row);
}
};
int main() {
matrix<int> m(3, 3);
for (int i=0; i<3; i++) // fill the matrix with identifiable numbers
for (int j=0; j<3; j++)
m[i][j] = i * 100 + j;
for (int i=0; i<3; i++) { // show the content
for (int j=0; j<3; j++)
std::cout << m[i][j] << "\t";
std::cout << "\n";
}
try { // test the bounds checking.
m[4][1] = 21;
}
catch(std::logic_error &e) {
std::cerr << e.what();
}
return 0;
}
So, when we create a matrix, we save its size in rows and cols. When we use operator[] on the matrix, that doesn't attempt to directly return a reference to an item in the matrix -- rather, it returns an instance of a proxy class that keeps track of the row and the matrix, and provides an operator[] of its own.
So, when you use matrix[a][b], The first one just saves a and matrix into a proxy object. Then the [b] part gets invoked on that proxy object. That checks that both a and b are within the bounds we saved for the matrix, and if so returns a reference to the correct object in the vector. Otherwise, it throws an std::Logic_error (may not be the best choice -- just the first one that occurred to me).
I should add that there are quite a few variations on this general idea. Just for one example, you could specify the size of the array at compile time, but passing the sizes as template parameters. This can have some advantages -- for example, matrix<int, 2, 3> and matrix<int, 3, 2> are entirely different types, so you can't accidentally assign one to the other. It can also have some disadvantages (most obviously, you need to know the size at compile time or it won't work at all).

Related

2-D array and pointer in C++ -- how to go through every every element using pointer of a 2-D matrix

For practice, I want to define a Matrix addition of two 2-D Matrces by pulling the pointers of them. Here is the initiation
const double A[2][2]={{1,2},{3,4}};
double B[2][2]={{4,3},{2,1}};
const double* a=*A;
double* b=*B;
However, since the pointer merely points to the first element of the first array within each matrix, a=*(A+0), how can i go through every element of each Matrix? And I only wnat to use pointer as parameter here.
void D2Add(const double*, double*){
...for loop here...
}
I only wnat to use pointer as parameter here
That way you will have undefined behavior. The different sub arrays may be placed in different pages/segments in memory and Accessing an array out of bounds is not guaranteed to work. I removed the sentence trying to explain a possible pitfall when accessing a sub array out of bounds because I can't find a good description of it right now.
One way to avoid undefined behavior is to take the arrays by reference instead:
#include <cstddef>
#include <iostream>
template<std::size_t Y, std::size_t X>
void D2Add(const double(&A)[Y][X], double(&B)[Y][X]) {
for(std::size_t y = 0; y < Y; ++y) {
for(std::size_t x = 0; x < X; ++x) {
B[y][x] += A[y][x];
}
}
}
int main() {
const double A[2][2]={{1,2},{3,4}};
double B[2][2]={{4,3},{2,1}};
D2Add(A, B);
for(auto& inner : B) {
for(auto value : inner) std::cout << value << ' ';
std::cout << '\n';
}
}
Output:
5 5
5 5
This is a very interesting question actually.
Formally, you're indeed only allowed to access the elements of the first sub-array, and trying to access the other one would cause undefined behavior.
But practically, there's a good chance that you might be able to loop from 0 to 4, treating the arrays as 1D arrays of size 4. But I would advise against doing this if possible.
I Hope you have good understanding of how Multi-Dimensional array is laid in memory.
problem- It is not possible by just pointers until your function has a way to know dimensions of array.
As specified, we need to pass dimensions to functions as well.
Since you only want to go through every element, I'll be print each element for demonstration.
void D2Add(const double* ptr, int nRow, int nCol) {
for (int i=0; i<nRow; i++) {
for (int j=0; j<nCol; j++) {
std::cout << *(ptr+(i*nCol)+j) << std::endl;
}
}
}

How to make an 2D array element in a class then specify its dimensions in its constructor?

I have a class for my console game engine, it has an array of characters for the map. In the constructor, I want to take parameters for the height and width of the map (the map is an array). I tried to declare and instantiate an array in the constructor however this array gets deleted after the constructor is done constructing. heres what it looked like:
class ConsoleGameEngine {
public:
ConsoleGameEngine(mapheight, mapwidth) {
char map[mapheight][mapwidth];
}
}
this didnt allow any other methods to access the map array as it was destroyed when the constructor finished. I want to do something like this:
class ConsoleGameEngine {
public:
char map;
ConsoleGameEngine(mapheight, mapwidth) {
map[mapheight][mapwidth];
}
}
i dont want to use vectors, i want to use normal arrays. Thank you for reading.
That's not possible. Arrays must have compile-time constant sizes in C++. See this question for an explanation of why. You could dynamically allocate it, but you would have to manage the memory which can get complicated. std::vector is probably the best option, and you can use a 1D vector by mapping 2D indices into 1D indices which is more efficient than a vector of vectors.
You can use a template. The parameters are known at compile time, so you can use them to define the dimensions of your array:
#include <iostream>
#include <cstdlib>
template < int nRows, int nCols>
class MyFunArray
{
public:
int m_nRows = nRows;
int m_nCols = nCols;
char map[nRows][nCols];
bool SetValue(char val, int row, int col)
{ if (row >= 0 && row < m_nRows && col >= 0 && col < m_nCols)
{ map[row][col] = val;
return true;
}
return false;
}
char GetValue(int row, int col)
{ if (row >= 0 && row < m_nRows && col >= 0 && col < m_nCols)
return map[row][col];
else
return '\0';
}
};
int main()
{
MyFunArray<3,4> myArr;
myArr.SetValue('b', 1,2);
std::cout << myArr.GetValue(1,2) << std::endl;
}
I have added Set/Get functions, just to code the bound limits. If you feel brave (and irresponsible) you can access map directly.
Just a complement on #AlexanderZhang's answer.
The least bad way is to use an underlying 1D vector which will handle dynamic memory management for you. But unfortunately, C++ has no support for anything close to multi-D containers.
Here is an old question of mine explaining the problem, with a very detailed answer from NicolBolas
Anyway, you will find there an implementation attempt that I submitted on Code Review - this one was the third try, and you will see that trying to mimic standard containers over multi-D arrays soon leads to some bit of complexity...

Passing a 2D array of unknown size to a function C++

Basically, my problem is: I have the user to define the size (N,M) of a 2D array and then I declare:
int matrix[N][M];
then I need to pass this uninitialized matrix to a function that reads some data from a .csv file and puts it into the matrix, so I tried:
void readwrite(int &matrix[N][], const int N, const int M){....};
int main(){
....
cin>>N;
cin>>M;
int matrix[N][M];
readwrite(matrix,N,M);
};
However, when i compile it, it gives me the following error: "N was not declared in this scope".
Any ideas of how to make this work?
Thank y'all!
What The OP is trying is so annoyingly difficult to get right and the benefits of pulling it off are so minuscule compared to the costs that... Well, I'll quote from the Classics.
The only winning move is not to play.
-Joshua, WarGames
You cannot safely pass a dynamically allocated 2D array in C++ into a function because you always have to know at least one dimension at compile time.
I could point over at Passing a 2D array to a C++ function because that looks like a good duplicate. I won't because it's referring to statically allocated arrays.
You can play silly casting games to force the array into the function, and then cast it back on the inside. I'm not going to explain how to do this because it is epic-class stupid and should be a firing offense.
You can pass a pointer to a pointer, int **, but the construction and destruction logic is a grotesque set of new and loops. Further, the end result scatters the allocated memory around the RAM, crippling the processors attempts at prediction and caching. On a modern processor if you can't predict and cache, you are throwing away the greater part of your CPU's performance.
What you want to do is stay one dimensional. A 1D array is easy to pass. The indexing arithmetic is dead simple and easy to predict. It's all one memory block so cache hits are more likely than not.
Making a 1D array is simple: Don't. Use std::vector instead.
std::vector<int> arr(rows*columns);
If you have to because the assignment spec says "No Vectors!" Well you're stuck.
int * arr = new int[rows*columns];
Note I'm using rows and columns not M and N. When faced with M and N which is which? Who knows, who cares, and why do this to yourself in the first place? Give your variables good, descriptive names and enjoy the time savings of being able to read your code when you are debugging it later.
The guts of usage are identical with array and vector:
int test = arr[row * columns + column];
Will recover the element in 2D space at [row][column]. I shouldn't have to explain what any of those variables mean. Death to M and N.
Defining a function is:
void function (std::vector<int> & arr, size_t rows, size_t columns)
or (yuck)
void function (int * arr, size_t rows, size_t columns)
Note that rows and columns are of type size_t. size_t is unsigned (a negative array size is not something you want, so why allow it?) and it is guaranteed to be big enough to hold the largest possible array index you can use. In other words it is a much better fit than int. But why pass rows and columns everywhere? The smart thing to do at this point is make a wrapper around an the array and its control variables and then bolt on a few functions to make the thing easier to use.
template<class TYPE>
class Matrix
{
private:
size_t rows, columns;
std::vector<TYPE> matrix;
public:
// no default constructor. Matrix is BORN ready.
Matrix(size_t numrows, size_t numcols):
rows(numrows), columns(numcols), matrix(rows * columns)
{
}
// vector handles the Rule of Three for you. Don't need copy and move constructors
// a destructor or assignment and move operators
// element accessor function
TYPE & operator()(size_t row, size_t column)
{
// check bounds here
return matrix[row * columns + column];
}
// constant element accessor function
TYPE operator()(size_t row, size_t column) const
{
// check bounds here
return matrix[row * columns + column];
}
// stupid little getter functions in case you need to know how big the matrix is
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
// and a handy-dandy stream output function
friend std::ostream & operator<<(std::ostream & out, const Matrix & in)
{
for (int i = 0; i < in.getRows(); i++)
{
for (int j = 0; j < in.getColumns(); j++)
{
out << in(i,j) << ' ';
}
out << '\n';
}
return out;
}
};
Rough bash-out of what the array version would have to look like just to show the benefits of allowing vector to do its job. Not tested. May contain howlers. The point is a lot more code and a lot more room for error.
template<class TYPE>
class ArrayMatrix
{
private:
size_t rows, columns;
TYPE * matrix;
public:
ArrayMatrix(size_t numrows, size_t numcols):
rows(numrows), columns(numcols), matrix(new TYPE[rows * columns])
{
}
// Array version needs the copy and move constructors to deal with that damn pointer
ArrayMatrix(const ArrayMatrix & source):
rows(source.rows), columns(source.columns), matrix(new TYPE[rows * columns])
{
for (size_t i = 0; i < rows * columns; i++)
{
matrix[i] = source.matrix[i];
}
}
ArrayMatrix(ArrayMatrix && source):
rows(source.rows), columns(source.columns), matrix(source.matrix)
{
source.rows = 0;
source.columns = 0;
source.matrix = nullptr;
}
// and it also needs a destructor
~ArrayMatrix()
{
delete[] matrix;
}
TYPE & operator()(size_t row, size_t column)
{
// check bounds here
return matrix[row * columns + column];
}
TYPE operator()(size_t row, size_t column) const
{
// check bounds here
return matrix[row * columns + column];
}
// and also needs assignment and move operator
ArrayMatrix<TYPE> & operator=(const ArrayMatrix &source)
{
ArrayMatrix temp(source);
swap(*this, temp); // copy and swap idiom. Read link below.
// not following it exactly because operator=(ArrayMatrix source)
// collides with operator=(ArrayMatrix && source) of move operator
return *this;
}
ArrayMatrix<TYPE> & operator=(ArrayMatrix && source)
{
delete[] matrix;
rows = source.rows;
columns = source.columns;
matrix = source.matrix;
source.rows = 0;
source.columns = 0;
source.matrix = nullptr;
return *this;
}
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
friend std::ostream & operator<<(std::ostream & out, const ArrayMatrix & in)
{
for (int i = 0; i < in.getRows(); i++)
{
for (int j = 0; j < in.getColumns(); j++)
{
out << in(i,j) << ' ';
}
out << std::endl;
}
return out;
}
//helper for swap.
friend void swap(ArrayMatrix& first, ArrayMatrix& second)
{
std::swap(first.rows, second.rows);
std::swap(first.columns, second.columns);
std::swap(first.matrix, second.matrix);
}
};
Creating one of these is
Matrix<int> arr(rows, columns);
Now passing the array around is
void func(Matrix & arr);
Using the array is
int test = arr(row, column);
All of the indexing math is hidden from sight.
Other references:
What is the copy-and-swap idiom?
What is The Rule of Three?
int &matrix[N][] - N has to be a compile-time constant, not just const and not at all a parameter. And reference to an array is declared like: int (&matrix)[size]
Try passing int **matrix, and you'll also need to change the way you create this array. Variable lenght arrays are not supported in C++, you'll need to allocate it's memory dynamically. Or rather, stick with std::vector, std::array if you knew the sizes at compile-time.

Passing smart pointers to a function

I have a two dimensional smart pointer array of doubles. I can assign values to it, and display it, but I am having trouble passing it to a function that takes double** as an input. A simple get() does not work.
#include <iostream>
#include <memory>
using namespace std;
# define DIM1 3
# define DIM2 4
void funcCall(double** item)
{
cout<< "Test function.";
}
int main() {
std::unique_ptr<std::unique_ptr<double[]>> myArray(new std::unique_ptr<double[]>[DIM1]);
for (int i = 0; i < DIM1; i++)
{
myArray.get()[i].reset(new double[DIM2]);
}
std::cout<<"Assign values"<<std::endl;
for (int i = 0; i < DIM2; i++)
{
for (int j = 0; j < DIM1; j++)
{
myArray.get()[j][i] = (j+1)*(i+1);
}
}
funcCall(myArray.get());
return 0;
}
When I compile this, I get:
error: cannot convert 'std::unique_ptr<std::unique_ptr<double []> >::pointer {aka std::unique_ptr<double []>*}' to 'double**' for argument '1' to 'void funcCall(double**)' funcCall(myArray.get())
void funcCall(std::unique_ptr<std::unique_ptr<double[]>> & arr)
Should do what you want, but...
but...
It sounds like you are trying to reinvent the wheel. Don't do that. Unless this is for an assignment or personal education, in that case go nuts.
Instead, use one of the built-in containers.
Because DIM1 and DIM2 are constant, you can use
std::array<std::array<double, DIM2>,DIM1> myArray;
and
void funcCall(std::array<std::array<double, DIM2>,DIM1> arr)
But odds are pretty good you want a dynamic solution. In that case, try
std::vector<std::vector<double>> myArray(DIM1, std::vector<double>(DIM2));
and
void funcCall(std::vector<std::vector<double>> arr)
but...
This is a sucker bet, to be honest. An array of arrays or a vector of vectors are not contiguous in memory so the computer has to hop around in storage, wasting time on unnecessary cache misses and the time spent loading and possibly reloading cache often take longer than the computations involved. All the 133t math in the world can't help you at this point because you've become gated by IO, and IO is sssssssssslllloooowwwwwwww.
What you really want is one nice 1 dimensional array that's indexed manually. with row * number of columns + column. Sure, manual index looks like extra work, but stop and think: How much math is the compiler doing in the background to make you array work, hmmm? Probably about the same. You just don't get to see it.
Let's stuck with std::vector for now, but the same applies to std::array or even a good ol' static array or a dynamic inside a smart pointer.
std::vector<double> myArray(DIM1*DIM2);
Using this is relatively simple:
myArray[row*DIM2 + column];
The function is:
void funcCall(std::vector<double> arr)
But this is easily wrapped in a class and simplified further:
class matrix
{
private:
std::vector<double> myArray;
size_t nrRows;
size_t nrColumns;
public:
matrix(size_t rows, size_t columns):
myArray(rows*columns), nrRows(rows), nrColumns(columns)
{
}
double& operator()(size_t row, size_t column)
{
return myArray[row* nrColumns + column];
}
double operator()(size_t row, size_t column) const
{
return myArray[row* nrColumns + column];
}
};
Construction:
matrix mat(DIM1, DIM2);
and usage:
double d = mat(1,2);
or
mat(2,1) = 3.14;
The types of the call and the function header don't match. You can't treat a unique_ptr as a regular pointer.
One solution is to change your function definition to:
void funcCall(std::unique_ptr<double[]> *item)

Own matrix class multiply operator

I wrote an IntegerMatrix class to add my own methods to work with matrices. Now I've written a function like this:
IntegerMatrix** IntegerMatrix::multiplyMatrix(IntegerMatrix** table2)
(It's a double pointer because I'm holding a huge array of pointers to 4x4 2D arrays.) so I simply could do this:
matrix1.multplyMatrix(matrix2)
One little problem is the * isn't defined for my own class. So I thought to overload this operator that I could do something like this:
sum += this->table[i][k] * table2[k][j];
But how can I get the right i and k in the overloaded operator, which is defined like this:
IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & k);
The only problem I can't figure out right now is how to get the right values ?
EDIT:
I've rewrote this and now I have:
IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & table2)
{
int i, j, k;
int sum;
IntegerMatrix * result = new IntegerMatrix(SIZE);
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
sum = 0;
for (k = 0; k < SIZE; k++) {
sum += this->table[i][k] * table2[k][j];
}
result[i][j] = sum;
}
}
return *result;
}
That gives me just an error on the [] :
Binary '[' : 'IntegerMatrix' does not define this operator or a conversiont o a type acceptable to the predefined operator.
I don't understand your question, but here's a brief demo of how matrix multiplication normall works:
class IntegerMatrix {
int table[3][3];
public:
IntegerMatrix& operator*=(const IntegerMatrix& rhs) {
//multiply table by rhs.table, store in data.
return *this;
}
};
IntegerMatrix operator*(IntegerMatrix lhs, const IntegerMatrix& rhs)
{return lhs*=rhs;} //lhs is a copy, so we can alter and return it
FOR YOUR EDIT
You have the code
IntegerMatrix * result = new IntegerMatrix(SIZE); //pointer to an IntegerMatrix
...
result[i][j] = sum; //assign sum to the jth index of matrix # i
when in actuality, I presume you wanted
result->table[i][j] = sum; //sum to the ixj index of the result matrix.
Also, your function is leaky, because you have a new, but no delete. This is easy to fix in your case, since you don't need the new. (Are you from a Java or C# background?)
IntegerMatrix result(SIZE);
...
result[i][j] = sum;
...
return result;
Unrelated to all of the above, you might actually want to provide a [] operator for your Integer Matrix.
class row {
int* data;
int size;
public:
row(int* d, int s) :data(d), size(s) {}
int& operator[](int offset) {
assert(offset<size);
return data[offset];
}
};
row operator[](int column) {
assert(column<SIZE);
return row(table[column], SIZE);
}
And this would allow you to write:
IntegerMatrix result;
result[i][j] = sum;
You may be carrying over some artifacts, in sort of a Cargo-Cult programming sense. :-/
For instance: I'm guessing that the double indirections (**) on your prototype for multiplyMatrix are there because you saw multidimensional arrays of integers around somewhere...stuff like:
void printMatrix(int ** myMatrix, int rows, int columns);
The double-indirection is just a pointer-to-a-pointer. It's a way of achieving the specific implementation point of passing low-level C-style 2D arrays as parameters. But it's not something you have to tack on any time you're working with an abstract class that happens to represent a Matrix. So once you've encapsulated the matrix size and data itself inside the IntegerMatrix class, you don't want something like this:
void printMatrix(IntegerMatrix ** myMatrix);
More likely you'd want to pass in a simple reference to the class which is encapsulating the data, like this:
void printMatrix(IntegerMatrix const & myMatrix);
You should actually return a new matrix from your multiplication function, at least if you're using it to implement an operator overload...because semantically it does not make sense for people to write things like a * b; and have that modify a. (It can, but you shouldn't.) So you are left with either the choice of returning a matrix value instance:
IntegerMatrix IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);
...or returning a pointer to a new object:
IntegerMatrix * IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);
Returning by pointer has historically been chosen by many libraries because returning by value from a local variable in the function would involve making a copy at the time of return. Returning a pointer is fast (it "copies" only one 32-bit/64-bit number) while copying an instance of an object and large blocks of data inside it is slow. So a lot of libraries would just use Matrix pointers everywhere...with the problem that it becomes hard to know whose responsibility it is to ultimately delete the object. Smart pointers are one way of ensuring this:
unique_ptr<IntegerMatrix> IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);
But C++11 has some sneaky ability to be just as fast without the mess. If you return something by value from a function and the compiler is sure that value isn't going to be used again (since it's going out of scope), then it can be "moved" about as fast as a pointer could. This requires that you support move construction by RValue reference, and there's all kinds of trickiness in that.
There's really a lot of nuance. If you're doing this as an educational exercise, I'd suggest taking it slowly and going through a tutorial that walks you through every step instead of jumping straight into the fire. And if you're using low-level C arrays and dynamic allocations inside your matrix, change them to a std::vector of std::vector.
For one IntegerMatrix object you're using this->table[i][k] to refer to the array where you're holding the matrix data, while for the table2 object reference and the result pointer, you're using table2[k][j] and result[i][j].
I think that what you want to do is something like:
IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & table2)
{
int i, j, k;
int sum;
IntegerMatrix * result = new IntegerMatrix(SIZE);
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
sum = 0;
for (k = 0; k < SIZE; k++) {
sum += this->table[i][k] * table2.table[k][j];
}
result->table[i][j] = sum;
}
}
return *result;
}