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;
}
Related
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.
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)
I want to add two arrays by simply writing:
int a[4] = {1,2,3,4};
int b[4] = {2,1,3,1};
int sum[4] = a + b;
I wrote this function but I got an error
int* operator+(const uint32& other) const{
uint32 sum[n];
for(int i=0; i<n; i++){
sum[i] = (*this[i]) + other[i];
}
return sum;
}
Could you help me on this? Thanks in advance.
Let's go through your code, piece by piece, and look at the problems:
int* operator+(const uint32& other) const{
You can't overload operators for built-in types, so this is doomed from the beginning
Even if you could do this (which you can't), it needs to take two parameters since it's non-member binary function.
uint32 sum[n];
You can't make variable-length arrays in C++ (assuming n isn't a compile-time constant) (note: G++ has some extensions that allow this, but it's non-standard C++)
for(int i=0; i<n; i++){
sum[i] = (*this[i]) + other[i];
There's no this pointer to begin with in this code (it's not a member function)...
const uint32& other is not an array/pointer to an array. It's a single reference to a single uint32. That means that other in this code is not an array/pointer to an array, and so you cannot do other[i] (it's like trying to do int x = 3; x[4] = 13;, which makes no sense).
}
return sum;
You're returning a pointer to a locally allocated array, which means this will result in undefined behavior, as the memory associated with sum is going to get annihilated when this function returns.
}
This is probably wrong, but it appears to work (C++11):
#include <iostream>
#include <array>
using namespace std;
template <class T>
T operator+(const T& a1, const T& a2)
{
T a;
for (typename T::size_type i = 0; i < a1.size(); i++)
a[i] = a1[i] + a2[i];
return a;
}
int main()
{
array<int,5> a1 = { 1, 2, 3, 4, 5 };
array<int,5> a2 = { 2, 3, 4, 5, 6 };
array<int,5> a3 = a1 + a2;
for (int i = 0; i < 5; i++)
cout << a1[i] << '+' << a2[i] << '=' << a3[i] << ' ';
cout << endl;
return 0;
}
Output (ideone):
1+2=3 2+3=5 3+4=7 4+5=9 5+6=11
I think the issue is that you're missing a way to pass in the length of the array. You might need to do something a bit more sophisticated. Something like:
class AddingVector : public std::vector<int>
{
public:
typedef AddingVector type;
type operator+(const AddingVector& rhs, const AddingVector& lhs)
{
/* validate that they're the same size, decide how you want to handle that*/
AddingVector retVal;
AddingVector::const_iterator rIter = rhs.begin();
AddingVector::const_iterator lIter = lhs.begin();
while (rIter != rhs.end() && lIter != lhs.end()) {
retVal.push_back(*rIter + *lIter);
++rIter;
++lIter;
}
return retVal;
}
}
You cannot do that. Non-member binary operators must take two arguments (you only provided one), so you could try this:
int* operator+(const uint32& a, const uint32& b)
But that can't possibly work either, since you want to add arrays, not single uint32 variables. So you would think that this would do it:
int* operator+(const uint32[] a, const uint32[] b)
or:
int* operator+(const uint32[4] a, const uint32[4] b)
But no go. It's illegal because you cannot have pointer types as both arguments in an operator overload. Additionally, at least one of the arguments must be a class type or an enum. So what you're trying to do is already impossible on at least two different levels.
It's impossible to do what you want. One correct way to go about it is to write your own class for an array that can be added to another one.
You cannot overload operators for types other than your own defined types. That is, if you create a class X, you can overload operators for X, but you cannot overload operators for arrays or pointers to fundamental types.
first is your code getting compiled properly, you have used 'n' directly in declaring array, is 'n' declared as constant..
And moreover you have taken a local variable in the function and returning it, well, this return a garbage form the stack, wat i can suggest is you malloc some memory and use it,, but again freeing it would be needed...
Hey, what you could do is,
Take a wrapper class "array"
class array
{
int *ipArr;
DWORD size;
};
then in constructor you can pass the size you want to have an array of
array(DWORD dwSize);
{
// then malloc memory of size dwSize;
}
Have an overloaded operator'+' for this class, that will have the above implementation of adding two int arrays,
Note here you will also need to overlaod the '=' assignment operator, so that our array class can you is directly..
now you can free the associated memory in the destructor
You have a few problems. The first is that you aren't passing in both arrays, and then you don't specify what n is, and the last is that you are trying to pass out a pointer to a local variable. It looks like you are trying to make a member operator of a class.
So basically you are trying to add the contents of an unspecified length array to an uninitialised array of the same length and return the stack memory.
So if you pass in pointers to the arrays and the length of the array and an output array then it would work, but you wouldn't have the syntax
sum = a + b;
it would be something like
addArray(&a, &b, &sum, 4);
To get the syntax you want you could make a class that wraps an array. But that is a much more complicated task.
I have my own mathematical Vector class that I use in my code. I have a new need to generalize my vector class to n dimensions instead of just two.
My question is, what's the best way to implement the operator overloads, and is there a significant overhead to doing this?
I now store the values in an array
double *vals;
....
vals = new double[dimension];
With this, I implement the + operator like so:
Vector Vector::operator+(Vector v)
{
Vector ret = Vector(dimension);
for (int i = 0; i < dimension; i ++)
{
ret.vals[i] = vals[i] + v.vals[i];
}
}
This operation will be done a LOT and has to run fast. Is this significantly worse than the old version (as far as speed)?
Vector Vector::operator+(Vector v) {
return Vector(x + v.x, y + v.y);
}
Thanks for any input!
If you want a fast vector class then use templates for the size:
template<std::size_t size>
class Vector {
double data[size];
public:
double& operator[](std::size_t x) { return data[x]; }
};
template<std::size_t size>
Vector<size> operator+(Vector<size> lhs, const Vector<size>& rhs) {
for (std::size_t i = 0; i < size; ++i)
lhs[i] += rhs[i];
return lhs;
}
Having them be dynamic size is only unnecessary if you want to re-size them, or if they are incredibly large.
There are ways to get much faster than this, such as SSE. You should use a dedicated math library if you want something highly optimized.
First, I would suggest passing your operand by reference instead of by value to avoid an unnecessary object copy:
Vector Vector::operator+(const Vector &v) {
Second, most compilers implement Return Value Optimization which will help eliminate the local ret in your multidimensional implementation.
The best approach, of course, is to implement your code, benchmark it, and then apply optimisations where necessary. Scott Meyers' Effective C++ is an excellent reference for the sort of thing you're attempting to do here.
I was implementing a small dense matrix class and instead of plan get/set operators I wanted to use operator overloading to make the API more usable and coherent.
What I want to achieve is pretty simple:
template<typename T>
class Matrix
{
public:
/* ... Leaving out CTOR and Memory Management for Simplicity */
T operator() (unsigned x, unsigned y){/* ... */ }
};
Matrix<int> m(10,10);
int value = m(5,3); // get the value at index 5,3
m(5,3) = 99; // set the value at index 5,3
While getting the value is straight forward by overloading operator(), I can't get my head around defining the setter. From what I understood the operator precedence would call operator() before the assignment, however it is not possible to overload operator() to return a correct lvalue.
What is the best approach to solve this problem?
I dispute that "it's not possible" to do the correct thing:
struct Matrix
{
int & operator()(size_t i, size_t j) { return data[i * Cols + j]; }
const int & operator()(size_t i, size_t j) const { return data[i * Cols + j]; }
/* ... */
private:
const size_t Rows, Cols;
int data[Rows * Cols]; // not real code!
};
Now you can say, m(2,3) = m(3,2) = -1; etc.
The answer to your question is what Kerrek already stated: you can provide an overload by changing the signature of the operator, which in this case can be achieved by modifying the const-ness of the function.
But I would recommend that you at least consider providing a separate setter for the values. The reason is that once you return references to your internal data structures you loose control of what external code does with your data. It might be ok in this case, but consider that if you decided to add range validation to the implementation (i.e. verify that no value in the matrix is above X or below Y), or wished to optimize some calculation on the matrix (say the sum of all of the elements in the matrix is an often checked value, and you want to optimize away the calculation by pre-caching the value and updating it on each field change) it is much easier to control with a method that receives the value to set.