vs10 compiler is this a bug? - c++

Mat2D.h
#pragma once
#include <iostream>
#include <iomanip>
#include <assert.h>
namespace Ggicci
{
template<class T>
class Mat2D
{
private:
int _rows;
int _cols;
T** _data;
public:
Mat2D()
:_rows(0), _cols(0), _data(NULL)
{
}
Mat2D(const Mat2D<T>& rhs)
:_rows(rhs._rows), _cols(rhs._cols)
{
allocateData();
cloneData(rhs._data);
}
Mat2D(int rows, int cols)
{
initSize(rows, cols);
allocateData();
all(0);
}
Mat2D(int rows, int cols, T initValue)
{
initSize(rows, cols);
allocateData();
all(initValue);
}
Mat2D(int rows, int cols, const T* data)
{
initSize(rows, cols);
allocateData();
assignData(data);
}
~Mat2D()
{
destroyData();
}
const Mat2D& operator = (const Mat2D<T>& rhs)
{
if (this == &rhs)
{
return *this;
}
this->resize(rhs._rows, rhs._cols);
this->cloneData(rhs._data);
return *this;
}
T& operator() (int row, int col)
{
assert(row >= 0 && row < _rows && col >= 0 && col < _cols);
return _data[row][col];
}
T operator() (int row, int col) const
{
assert(row >= 0 && row < _rows && col >= 0 && col < _cols);
return _data[row][col];
}
Mat2D<T> operator * (const Mat2D<T>& rhs)
{
assert(this->_cols == rhs._rows);
int new_rows = this->_rows;
int new_cols = rhs._cols;
Mat2D<T> result(new_rows, new_cols);
for (int i = 0; i < new_rows; i++)
{
for (int j = 0; j < new_cols; j++)
{
T sum = 0;
for (int k = 0; k < this->_cols; k++)
{
sum += this->_data[i][k] * rhs._data[k][j];
}
result._data[i][j] = sum;
}
}
return result;
}
void resize(int rows, int cols)
{
destroyData();
initSize(rows, cols);
allocateData();
all(0);
}
void all(T value)
{
for (int i = 0; i < _rows; i++)
for (int j = 0; j < _cols; j++)
_data[i][j] = value;
}
private:
void initSize(int rows, int cols)
{
assert(rows > 0 && cols > 0 && rows < 65536 && cols < 65536);
_rows = rows;
_cols = cols;
}
void allocateData()
{
_data = new T*[_rows];
for(int i = 0; i < _rows; i++)
{
_data[i] = new T[_cols];
}
}
void assignData(const T* data)
{
for (int i = 0; i < _rows; i++)
{
for (int j = 0; j < _cols; j++)
{
_data[i][j] = data[i*_rows + j];
}
}
}
void cloneData(T** data)
{
for (int i = 0; i < _rows; i++)
for (int j = 0; j < _cols; j++)
_data[i][j] = data[i][j];
}
void destroyData()
{
for(int i = 0; i < _rows; i++)
delete _data[i];
delete _data;
}
/*template<class T>*/ //--> Line 158
friend std::ostream& operator << (std::ostream& out, const Mat2D<T>& rhs)
{
for(int i = 0; i < rhs._rows; i++)
{
for(int j = 0; j < rhs._cols; j++)
{
out << std::setw(12) << rhs._data[i][j];
}
out << std::endl;
}
return out;
}
};
}
main.cpp
#include <iostream>
#include <string>
#include <cmath>
#include "Mat2D.h"
using namespace std;
using namespace Ggicci;
Mat2D<float> getRotateMatrix33f(float theta, const Mat2D<float>& ref_point = Mat2D<float>(1, 2, 0.0f))
{
theta = theta / 180 * 3.1415f;
float rotate[] = {
cos(theta), -sin(theta), 0,
sin(theta), cos(theta), 0,
0, 0, 1
};
Mat2D<float> result(3, 3, rotate);
if (ref_point(0, 0) != 0 && ref_point(0, 1) != 0)
{
float dx = ref_point(0, 0);
float dy = ref_point(0, 1);
float translate_data[] = {
1, 0, 0,
0, 1, 0,
dx, dy, 1
};
float translate_inv_data[] = {
1, 0, 0,
0, 1, 0,
-dx, -dy, 1
};
Mat2D<float> translate(3, 3, translate_data);
Mat2D<float> translate_inv(3, 3, translate_inv_data);
result = translate * result * translate_inv;
}
return result;
}
int main()
{
int data_a[] = {1, 2};
int data_b[] = {2, 3, 4, 5, 6, 7, 8, 9};
Mat2D<int> a(1, 2, data_a);
Mat2D<int> b(2, 4, data_b);
Mat2D<int> c;
c = a * b;
cout << "c = " << endl << c << endl;
cout << "rotate matrix: " << endl << getRotateMatrix33f(30.0f) << endl;
return 0;
}
If I comment line 158 in Mat2D.h, every thing is okay, the project can build and run successfully though 4 errors occur:
If I don't comment line 158,
error C2995: 'std::ostream &Ggicci::operator <<(std::ostream &,const Ggicci::Mat2D<T>
&)' : function template has already been defined.
Then I comment the function getRotateMatrix33f and its invoking in main the project rebuild and run successfully with no errors.
So what happened? It confused me...

There is actually no error after commenting line 158, but C++ intellisense still think of your old code or probably mistake in parsing your code, MSVC team accepted this to be a bug in their intellisense engine but they said that they can't fix it untill MSVC2012, so if you can please test your code with that version

Related

Matrix C++ problem with overloading operators

I'm making simple matrix calculator for school project. I tried to use overloading operators but I have problem with operator "=". I checked it in debugger in Visual Studio and after assigning data from matrix A to matrix X all of data disappears. How should I repair this? Thank you in advance for your help and advice.
#include <iostream>
#include <vector>
#include <conio.h>
#include <stdlib.h>
using std::vector;
class Matrix {
private:
int rows, cols;
vector<vector<double>> matrix;
public:
Matrix(int r = 0, int c = 0) : rows(r), cols(c) {
std::vector<std::vector<double>> M(rows, std::vector<double>(cols));
matrix = M;
}
~Matrix() {}
// void operator+(const Matrix &rhs);
double get_rows() { return rows; }
double get_cols() { return cols; }
void set_matrix_value() {
std::cout << "Put values in your matrix\n";
for(int i = 0; i < matrix.size(); i++) {
for(int j = 0; j < matrix[i].size(); j++) {
// this->matrix[i][j] = int(_getch() - '0');
std::cin >> matrix[i][j];
}
}
}
void display_matrix() {
for(int i = 0; i < matrix.size(); i++) {
std::cout << "|";
for(int j = 0; j < matrix[i].size(); j++) {
std::cout << matrix[i][j];
if(j != matrix[i].size() - 1) {
std::cout << " ";
}
}
std::cout << "|\n";
}
}
Matrix operator=(const Matrix& M) {
rows = M.rows;
cols = M.cols;
Matrix new_matrix(rows, cols);
std::vector<std::vector<double>> m(rows, std::vector<double>(cols));
new_matrix.matrix = m;
for(int i = 0; i < m.size(); i++) {
for(int j = 0; j < m[i].size(); j++) {
new_matrix.matrix[i][j] = M.matrix[i][j];
}
}
return new_matrix;
}
Matrix operator+(const Matrix& m) {
if(rows != m.rows && cols != m.cols) {
std::cout << "Matrix sizes do not match. Write martix again.";
return (*this);
}
Matrix new_matrix(rows, cols);
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
new_matrix.matrix[i][j] = matrix[i][j] + m.matrix[i][j];
}
}
return new_matrix;
}
};
int main() {
// int k;
// int rows, cols;
Matrix X;
// std::cout << "Welcome in Matrix Mode!\n";
X.display_matrix();
Matrix A(3, 3);
A.set_matrix_value();
A.display_matrix();
X = A;
std::cout << X.get_rows() << " " << X.get_cols();
X.display_matrix();
}

Matrix class content using shared_ptr?

class Matrix
{
private:
int rows;
int cols;
int** Mat;
public:
Matrix(){}
Matrix(const int& rows, const int& cols):rows(rows),cols(cols)
{
Mat = new int* [cols];
for (int i = 0; i < rows; i++)
{
Mat[i] = new int[cols]();
}
}
Matrix operator +(const Matrix& other)const
{
Matrix temp(rows, cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
temp.Mat[i][j] += other.Mat[i][j] + Mat[i][j];
return temp;
}
My question is regarding how I'd use shared_ptr and make_shared to replace int** Mat? and, after that, how do I use it in the constructor and operator+? It's a custom matrix class that should add matrices
#include <iostream>
#include <memory>
#include <cassert>
class Matrix {
private:
int rows;
int cols;
std::shared_ptr<std::shared_ptr<int>> Mat;
public:
Matrix() = default;
Matrix(const int& rows, const int& cols) : rows(rows), cols(cols)
{
Mat.reset(new std::shared_ptr<int>[rows], [](std::shared_ptr<int>* p) { delete[] p; });
for (int i = 0; i < rows; ++i)
{
Mat.get()[i].reset(new int[cols], [](int* p) { delete[] p; });
}
for (int i = 0; i < (*this).rows; ++i)
for (int j = 0; j < (*this).cols; ++j)
(*this)[i][j] = 0;
}
int* operator[](const int& index) const
{
return Mat.get()[index].get();
}
Matrix(const Matrix& other) : cols(other.cols), rows(other.rows)
{
Mat.reset(new std::shared_ptr<int>[rows], [](std::shared_ptr<int>* p) { delete[] p; });
for (int i = 0; i < rows; ++i)
{
Mat.get()[i].reset(new int[other.cols], [](int* p) { delete[] p; });
}
for (int i = 0; i < other.rows; i++)
for (int j = 0; j < other.cols; j++)
(*this)[i][j] = other[i][j];
}
Matrix& operator=(const Matrix& other)
{
if (Mat != other.Mat && cols == other.cols && rows == other.rows)
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
(*this)[i][j] = other[i][j];
return *this;
}
else
return *this;
}
Matrix operator+(const Matrix& other) const
{
Matrix temp(rows, cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
temp[i][j] += other[i][j] + (*this)[i][j];
return temp;
}
friend std::ostream& operator<<(std::ostream& os, Matrix& m)
{
for (int i = 0; i < m.rows; ++i)
{
for (int j = 0; j < m.cols; ++j)
{
os << m[i][j] << " ";
}
os << std::endl;
}
return os;
}
};
int main()
{
Matrix a(2, 2);
a[0][0] = 1;
a[0][1] = 1;
std::cout << a << std::endl;
Matrix b(2, 2);
b[1][1] = 1;
b[1][0] = 1;
std::cout << b << std::endl;
b[1][0] = 9;
Matrix c(a);
c[0][0] = 6;
std::cout << c << std::endl;
Matrix d = b;
std::cout << d << std::endl;
Matrix e = a + b;
std::cout << e << std::endl;
}
I have solved it myself in the end :D

Matrix is represented as a single array in memory and Problem with matrix multiplication

I tried to make the Matrix header file. I also gave it a go at representing the matrix with a single array. Every method I wrote worked just fine. On the contrary, I couldn't figure out the problem with the matrix multiplication.
It seems fine though. I have stripped some code to make it small.
any help is appreciated.
#ifndef MATRIX_HPP
#define MATRIX_HPP
#include <iostream>
#include <random>
#include <chrono>
#include <ctime>
#include <iomanip>
using std::cout;
using std::endl;
using std::ios;
static std::ostream & pretty_print(std::ostream & output) {
output.setf(ios::showpoint);
output.setf(ios::showpos);
output.width(6);
output.precision(2);
return output;
}
class Matrix {
public:
// Constructor functions
Matrix();
Matrix(size_t r, size_t c, double v = 0);
Matrix(size_t r, size_t c, double *array);
Matrix(const Matrix &mat);
// helping functions
void randomize(double a = -1, double b = 1);
void addMat(const Matrix &mat);
void subMat(const Matrix &mat);
void multiply_matrix(const Matrix &mat);
Matrix transpose();
double* toArray();
void display();
// Static functions
static Matrix matMul(const Matrix &mat1, const Matrix &mat2);
static Matrix transpose(const Matrix &mat);
static Matrix fromArray(double *arr, size_t size);
// Overloaded operator functions and some friend functions
/*friend ostream& operator<<(ostream &dout, Matrix &mat);
friend istream& operator>>(istream &din, Matrix &mat);*/
private:
size_t rows;
size_t cols;
double *matrix;
// Random number engine
static uint32_t generate_seed();
static double get_random(double a,double b);
};
// Private static functions
uint32_t Matrix::generate_seed() {
{
std::random_device random;
if (random.entropy() > 0.0) {
return random();
}
}
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
}
//--------------------------------------------------------------------
double Matrix::get_random(double a, double b) {
static std::mt19937 random(Matrix::generate_seed());
std::uniform_real_distribution<double> double_dist{a, b};
return double_dist(random);
}
//--------------------------------------------------------------------
Matrix::Matrix() {
rows = 0;
cols = 0;
matrix = new double[rows * cols];
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
*(matrix + i * cols + j) = 0;
}
}
}
//--------------------------------------------------------------------
Matrix::Matrix::Matrix(size_t r, size_t c, double v) {
rows = r;
cols = c;
matrix = new double[rows * cols];
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
*(matrix + i * cols + j) = v;
}
}
}
//--------------------------------------------------------------------
Matrix::Matrix(size_t r, size_t c, double *array) {
rows = r;
cols = c;
matrix = new double[rows * cols];
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
*(matrix + i * cols + j) = *(array + i * cols + j);
}
}
}
//----------------------------------------------------------------
Matrix::Matrix(const Matrix &mat) {
rows = mat.rows;
cols = mat.cols;
matrix = new double[rows * cols];
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
*(matrix + i * cols + j) = *(mat.matrix + i * rows + cols);
}
}
}
//------------------------------------------------------------------
void Matrix::randomize(double a, double b) {
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
*(matrix + i * cols + j) = Matrix::get_random(a, b);
}
}
}
//-----------------------------------------------------------------------
Matrix Matrix::transpose() {
Matrix result(cols, rows);
for (size_t i = 0; i < result.rows; i++) {
for (size_t j = 0; j < result.cols; j++) {
*(result.matrix + i * result.cols + j) = *(matrix + j * cols + i);
}
}
return result;
}
//-----------------------------------------------------------------------
void Matrix::display() {
cout<<"[";
for (size_t i = 0; i < rows; i++) {
cout<<"[";
for (size_t j = 0; j < cols; j++) {
if (j != cols - 1) {
cout<<pretty_print<<*(matrix + i * cols + j)<<", ";
} else if (i != rows - 1 && j == cols - 1) {
cout<<pretty_print<<*(matrix + i * cols + j)<<"],"<<endl<<" ";
} else if (i == rows - 1 && j == cols - 1) {
cout<<pretty_print<<*(matrix + i * cols + j)<<"]]"<<endl;
}
}
}
cout<<endl;
}
//-----------------------------------------------------------------------
Matrix Matrix::matMul(const Matrix& mat1, const Matrix& mat2) {
if (mat1.cols == mat2.rows) {
Matrix result(mat1.rows, mat2.cols);
double sum; // mat1[i][k] * mat2[k][j];
for (size_t i = 0; i < result.rows; i++) {
for (size_t j = 0; j < result.cols; j++) {
sum = 0;
for (size_t k = 0; k < mat1.cols; k++) {
sum += *(mat1.matrix + i * mat1.cols + k) * *(mat2.matrix + k * mat2.cols + j);
}
*(result.matrix + i * result.cols + j) = sum;
}
}
return result;
} else {
cout<<"Matrix multiplication is not possible!"<<endl;
return Matrix();
}
}

C++ replacing matrix values with sub-matrix values

I have a University assignment whereby I have a 1D array, containing 262144 values. I've created a matrix class which places these values into an object with the datasource being the double* list of 262144 values.
I need to be able to obtain a sub-matrix (which I'm able to do) from ANOTHER set of 262144 values (which I've also placed into a matrix object).
However, I'm having serious trouble and I've been trying so hard for the last 3 days to try and replace original matrix values from a sub-matrix. I've tried passing by reference, creating Matrix*'s. I've tried everything we've been taught and even researched a few more methods, all of which I haven't understood. I'll throw my code in here to see if anyone can explain a method to me which will be able to do this.
Matrix::Matrix()
{
"Matrix::Matrix() is invoked";
}
Matrix::Matrix(const Matrix& m)
{
"Matrix::Matrix(const Matrix&) is invoked";
_M = m._M;
_N = m._N;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = m._data[i];
}
}
Matrix::Matrix(int sizeR, int sizeC, double *input_data)
{
"Matrix::Matrix(int sizeR, int sizeC, double *input_data is invoked";
_M = sizeR;
_N = sizeC;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = input_data[i];
}
}
Matrix Matrix::get_Block(int start_row, int end_row, int start_coloumn, int end_coloumn)
{
int rows = (end_row - start_row);
int columns = (end_coloumn - start_coloumn);
int ctr = 0;
double *temp_Data = new double[rows*columns];
for (int x = start_row; x < (rows + start_row); x++)
{
for (int y = start_coloumn; y < (columns + start_coloumn); y++)
{
temp_Data[ctr] = get(x, y);
ctr++;
}
}
Matrix block(rows, columns, temp_Data);
delete[] temp_Data;
return block;
}
Matrix Matrix::operator+(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] + other._data[x];
}
return temp;
}
Matrix Matrix::operator*(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] * other._data[x];
}
return temp;
}
Matrix Matrix::operator-(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] - other._data[x];
}
return temp;
}
void Matrix::replace_Block(Matrix& noisy, Matrix& shuffled,int k, int j, int i)
{
int val_to_replace = 0;
for (int i = 0; i < 3 * 3; i++)
{
val_to_replace = shuffled.get(i, j);
noisy.set(i, j, val_to_replace);
}
}
void Matrix::set_Block(Matrix block, Matrix& Noisy, int start_row, int end_row)
{
int ctr = 0;
int ctr2 = 0;
int ctr3 = 0;
for (int i = 0; i < 3; i++)
{
Noisy._data[(start_row*_M)+i+4] = block.get(i, ctr);
ctr++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 3] = block.get(j, ctr2);
ctr2++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 2] = block.get(j, ctr3);
ctr3++;
}
}
double Matrix::get_Sum(Matrix m)
{
double total = 0;
short row = m.get_M();
short column = m.get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m.get(j,i);
}
}
return total;
}
double Matrix::get_Sum(Matrix* m)
{
double total = 0;
short row = m->get_M();
short column = m->get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m->get(i, j);
}
}
return total;
}
double Matrix::get(int i, int j)
{
return _data[(i * _M) + j];
}
void Matrix::write_Block(int i, int j)
{
for (int ctr = 0; ctr < i; ctr++)
{
for (int ctr2 = 0; ctr2 < j; ctr2++)
{
std::cout << " " << this->get(ctr,ctr2);
}
std::cout << std::endl;
}
}
void Matrix::set(int i, int j, double val)
{
this->_data[(i*_M) + j] = val;
}
void Matrix::set_N(int N)
{
_N = N;
}
void Matrix::set_M(int M)
{
_M = M;
}
int Matrix::get_N()
{
return _N;
}
int Matrix::get_M()
{
return _M;
}
Matrix::~Matrix()
{
"Matrix::~Matrix() is invoked";
delete[] _data;
}
If it would be helpful to see main() I can supply that too, however all it really contains is the creation of the matrix objects using overloaded constructors.
explanation
Answer is only 4 years late . . .
Anyway. Maybe it will help somebody else. The secret is to use a std::valarray. With that it is utmost simple to work on a matrix. And, many many functions are available.
All the functions that you want to implement are already available.
And you sub-matrix coy can be a one liner . . .
Please see example code:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <valarray>
#include <iomanip>
constexpr size_t NRows = 6;
constexpr size_t NCols = 8;
constexpr size_t SubNRows = 2;
constexpr size_t SubNCols = 3;
void debugPrint(std::valarray<int> &v, size_t nrows = NRows, size_t ncols = NCols)
{
for (int r = 0; r < nrows; ++r) {
for (int c = 0; c < ncols; ++c)
std::cout << std::setw(3) << v[r*ncols+c] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
int main()
{
std::valarray<int> v1(NRows * NCols); // Define array with given size
std::iota(std::begin(v1),std::end(v1),0); // Fill the array with consecutive nunbers
debugPrint (v1); // Print the result
std::cout << "\nSum = " << v1.sum() << "\n\n"; // Print the sum of all values in matrix
std::valarray<int> v2(v1); // Create a 2nd matrix as a copy to the first
v2 += 100; // Add 100 to each value in the matrix
debugPrint(v2);
std::valarray<int> v3(NCols); // Get one column
v3 = v1[std::slice(2,NRows,NCols)];
debugPrint(v3,NRows,1);
std::valarray<int> subV2(SubNRows*SubNCols); // So, now the sub array
subV2 = v2[std::gslice(12,{SubNRows, SubNCols},{NCols,1})]; // Slice it out
debugPrint(subV2, SubNRows, SubNCols);
v1[std::gslice(25,{SubNRows, SubNCols},{NCols,1})] = subV2; // And copy to the first array
debugPrint (v1);
return 0;
}

C++ OOP - Arrays (matrices) multiplication, deleting object [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 7 years ago.
I am writing simple C++ application to multiply two matrices. Yes, I am aware this version doesn't check e.g. whether number of rows is greater than zero.
I can create two objects using a default constructor and I can create third object (a result of multiplication of two previous objects of the same class). I can't however correctly delete this third object. When I try, an "Access violation reading location" exception is throw. Can you tell me what am I missing? Is there something I forget to initialize? This exception is only thrown when using myThirdFunction.
Any other advice on making this code better is welcome :)
#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;
class MyArray
{
int Variable1 = 0;
int Variable2 = 0;
float ** myArray;
public:
MyArray() : Variable1(0), Variable2(0){ myFunction(); }
MyArray (int variable1, int variable2) : Variable1(variable1):
Variable2(variable2){ myFunction(); }
MyArray(const MyArray &myArrayA, const MyArray &myArrayB) :
Variable1(myArrayA.Variable1), Variable2(myArrayB.Variable2)
{ myThirdFunction(myArrayA, myArrayB); }
MyArray(const MyArray &myArray)
{ Variable1=myArray.Variable1; Variable2 = myArray.Variable2;
this->myArray =myArray.myArray; }
void myFunction() {
cin >> Variable1;
cin >> Variable2;
myArray = new float*[Variable1];
myOtherFunction();
}
void myOtherFunction() {
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
myArray[i][j] = rand() % (10 - 0) + 0;
}
}
void myThirdFunction(MyArray myArrayA, MyArray myArrayB)
{
Variable1 = myArrayA.Variable1;
Variable2 = myArrayB.Variable2;
myArray = new float*[Variable1];
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
{
float tempVariable = 0;
for (int q = 0; q < myArrayA.Variable2; ++q)
{
tempVariable += myArrayA.myArray[i][q] * myArrayB.myArray[q][j];
}
myArray[i][j] = tempVariable;
}
}
}
void displayMyArray() {
for (int i = 0; i < Variable1; ++i)
{
for (int j = 0; j < Variable2; ++j)
cout << myArray[i][j] << '\t';
cout << endl;
}
}
~MyArray() {
for (int i = 0; i < Variable1; ++i)
{
delete[] myArray[i];
}
delete[]myArray;
}
};
int main(){
srand(time(0));
MyArray myArrayA;
myArrayA.displayMyArray();
cout << endl;
MyArray myArrayB;
myArrayB.displayMyArray();
cout << endl;
MyArray myArrayC(myArrayA, myArrayB);
myArrayC.displayMyArray();
getchar();
getchar();
return 0;
}
Thanks :)
The member myArray is a pointer, and in your copy constructor you just copy the pointer without creating a new array. Because myThirdFunction takes both arguments by value, it creates two copies of the original objects. And because the copy constructor doesn't create a new value, when those two copies go out of scope at the end of the function, the original pointers now point to deallocated memory. Whenever the original two objects are destroyed, the destructor tries to delete memory that was already deleted.
From the beginning, you have this constructor:
MyArray(const MyArray &myArrayA, const MyArray &myArrayB)
{
myThirdFunction(myArrayA, myArrayB); //This call creates two new objects
}
The signature of myThirdFunction being void myThirdFunction(MyArray myArrayA, MyArray myArrayB), you pass by value and create two new copies. That calls the copy constructors for the two parameters:
MyArray(const MyArray &myArray)
{
this->myArray =myArray.myArray; //shallow copy, very bad
}
The new objects now point to the same memory as the originals. So, when they are destroyed at the end of myThirdFunction, the original pointers become garbage. In a broad view, this happens. float* p = new float; delete p; delete p; The solution is to make the copy constructor actually copy the elements, not the pointers:
MyArray(const MyArray &p_copy) //The name confused me so I changed it
{
Variable1 = p_copy.Variable1;
Variable2 = p_copy.Variable2;
myArray new float*[Variable1];
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
myArray[i][j] = p_copy.myArray[i][j];
}
}
In addition, you probably want to pass to myThirdFunction by constant reference.
void myThirdFunction(const MyArray& myArrayA, const MyArray& myArrayB)
I don't see a need to create two temporary objects here.
At the first time this code will works.
#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;
class MyArray
{
int Variable1;
int Variable2;
float ** myArray;
public:
MyArray() : myArray(NULL), Variable1(0), Variable2(0) // initialize pointers with NULL is important
{
myFunction();
}
MyArray (int variable1, int variable2) : myArray(NULL), Variable1(variable1),
Variable2(variable2)
{
myFunction();
}
MyArray(const MyArray &myArrayA, const MyArray &myArrayB) : myArray(NULL),
Variable1(myArrayA.Variable1), Variable2(myArrayB.Variable2)
{
myThirdFunction(myArrayA, myArrayB);
}
MyArray(const MyArray &myArray)
{
Variable1=myArray.Variable1; Variable2 = myArray.Variable2;
this->myArray =myArray.myArray;
}
void myFunction()
{
cin >> Variable1;
cin >> Variable2;
myArray = new float*[Variable1];
myOtherFunction();
}
void myOtherFunction()
{
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
myArray[i][j] = rand() % (10 - 0) + 0;
}
}
void myThirdFunction(MyArray myArrayA, MyArray myArrayB)
{
// cols of first must be same as rows of second
if (myArrayA.Variable2 != myArrayB.Variable1)
return;
// memory must be cleaned before new array creation
clearArray();
Variable1 = myArrayA.Variable1;
Variable2 = myArrayB.Variable2;
myArray = new float*[Variable1];
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
{
float tempVariable = 0;
for (int q = 0; q < myArrayA.Variable2; ++q)
{
tempVariable += myArrayA.myArray[i][q] * myArrayB.myArray[q][j];
}
myArray[i][j] = tempVariable;
}
}
}
void displayMyArray()
{
for (int i = 0; i < Variable1; ++i)
{
for (int j = 0; j < Variable2; ++j)
cout << myArray[i][j] << '\t';
cout << endl;
}
}
~MyArray()
{
clearArray();
}
// clear memory and deinitialize pointers
void clearArray()
{
if (myArray == NULL)
return;
for (int i = 0; i < Variable1; ++i)
{
delete[] myArray[i];
myArray[i] = NULL;
}
delete[]myArray;
myArray = NULL;
}
};
int main(){
srand(time(0));
MyArray myArrayA;
myArrayA.displayMyArray();
cout << endl;
MyArray myArrayB;
myArrayB.displayMyArray();
cout << endl;
MyArray myArrayC(myArrayA, myArrayB);
myArrayC.displayMyArray();
getchar();
getchar();
return 0;
}
but I strongly recomend you to create proper copy constructor and assignment operator means (operator=) to proper object creation and destruction.
Here I post my own matrix realization to refer you in what way you can approve your code.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
using namespace std::
class Matrix
{
public:
Matrix();
Matrix(int rowcount,int colcount);
Matrix(int rowcount,int colcount,float* matrix);
Matrix(const Matrix& rhs);
~Matrix();
/////////////////////////////////////////////////////////////
Matrix& operator = (const Matrix& rhs);
Matrix operator + (const Matrix& rhs);
Matrix operator - (const Matrix& rhs);
Matrix operator * (float scale);
Matrix operator * (const Matrix& rhs);
void operator += (const Matrix& rhs);
void operator -= (const Matrix& rhs);
void operator *= (float scale);
void operator *= (const Matrix& rhs);
float operator [] (int offset) const;
float& operator [] (int offset);
friend ostream& operator << (ostream& _str,const Matrix& rhs);
/////////////////////////////////////////////////////////////
void setCols(int cols);
void setRows(int rows);
void setMatrix(float* matrix);
int getCols() const
{
return itsCols;
}
int getRows() const
{
return itsRows;
}
const float* getMatrix() const
{
Invariants();
return itsMatrix;
}
void Invariants() const
{
if ((!(itsCols && itsRows && itsMatrix)) && (itsRows < 0) && (itsCols < 0))
{
cout << "Not allowed action!\n";
getch();
exit(0);
}
}
/////////////////////////////////////////////////////////////
private:
float* itsMatrix;
int itsRows;
int itsCols;
};
Matrix::Matrix()
{
itsRows = 0;
itsCols = 0;
itsMatrix = NULL;
}
Matrix::Matrix(int rowcount,int colcount)
{
itsRows = rowcount;
itsCols = colcount;
itsMatrix = new float[itsRows * itsCols];
Invariants();
}
Matrix::Matrix(int rowcount,int colcount,float* matrix)
{
itsRows = rowcount;
itsCols = colcount;
itsMatrix = new float[itsCols * itsRows];
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
itsMatrix[counter] = matrix[counter];
counter++;
}
}
Invariants();
}
Matrix::Matrix(const Matrix& rhs)
{
itsCols = rhs.getCols();
itsRows = rhs.getRows();
itsMatrix = new float[itsRows * itsCols];
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
itsMatrix[counter] = rhs[counter];
counter++;
}
}
}
Matrix::~Matrix()
{
itsCols = 0;
itsRows = 0;
delete [] itsMatrix;
itsMatrix = NULL;
}
Matrix& Matrix::operator = (const Matrix& rhs)
{
if (&rhs == this)
return *this;
else
{
itsRows = rhs.getRows();
itsCols = rhs.getCols();
delete [] itsMatrix;
itsMatrix = NULL;
itsMatrix = new float[itsRows * itsCols];
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
itsMatrix[counter] = rhs[counter];
counter++;
}
}
return *this;
}
}
float& Matrix::operator [] (int offset)
{
Invariants();
if ((offset > -1) && (offset < itsCols * itsRows))
return itsMatrix[offset];
else
{
cout << "You cann't reach this element!\n";
getch();
exit(0);
}
return itsMatrix[offset];
}
float Matrix::operator [] (int offset) const
{
Invariants();
if ((offset > -1) && (offset < itsCols * itsRows))
return itsMatrix[offset];
else
{
cout << "You cann't reach this element!\n";
getch();
exit(0);
}
return 0;
}
Matrix Matrix::operator + (const Matrix& rhs)
{
Invariants();
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform addiction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] + rhs[counter];
counter++;
}
}
return temp;
}
Matrix Matrix::operator - (const Matrix& rhs)
{
Invariants();
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform substraction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] - rhs[counter];
counter++;
}
}
return temp;
}
Matrix Matrix::operator * (float scale)
{
Invariants();
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] * scale;
counter++;
}
}
return temp;
}
Matrix Matrix::operator * (const Matrix& rhs)
{
Invariants();
if (!(itsCols == rhs.getRows()))
{
cout << "Cann't perform multiplication of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,rhs.getCols());
int counter = 0;
float sum = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < rhs.getCols(); j++)
{
for (int k = 0; k < itsCols; k++)
{
sum += itsMatrix[i * itsCols + k] *
rhs[k * rhs.getCols() + j];
}
temp[counter] = sum;
sum = 0;
counter++;
}
}
return temp;
}
void Matrix::operator += (const Matrix& rhs)
{
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform addiction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] + rhs[counter];
counter++;
}
}
*this = temp;
}
void Matrix::operator -= (const Matrix& rhs)
{
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform substraction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] - rhs[counter];
counter++;
}
}
*this = temp;
}
void Matrix::operator *= (float scale)
{
Invariants();
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] * scale;
counter++;
}
}
*this = temp;
}
void Matrix::operator *= (const Matrix& rhs)
{
Invariants();
if (!(itsCols == rhs.getRows()))
{
cout << "Cann't perform multiplication of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,rhs.getCols());
int counter = 0;
float sum = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < rhs.getCols(); j++)
{
for (int k = 0; k < itsCols; k++)
{
sum += itsMatrix[i * itsCols + k] *
rhs[k * rhs.getCols() + j];
}
temp[counter] = sum;
sum = 0;
counter++;
}
}
*this = temp;
}
ostream& operator << (ostream& _str,const Matrix& rhs)
{
rhs.Invariants();
int counter = 0;
for (int i = 0; i < rhs.getRows(); i++)
{
for (int j = 0; j < rhs.getCols(); j++)
{
_str << rhs[counter] << "\t";
counter++;
}
_str << endl;
}
return _str;
}
float arr1[] =
{
2, 2, 2,
-1, -3, -5,
16, 8, 24,
8, 0, 16
};
float arr2[] =
{
15,
2,
-4
};
int main()
{
clrscr();
Matrix m1(4,3,arr1);
Matrix m2(3,1,arr2);
cout << "Matrix 1:\n";
cout << m1 << endl;
cout << "Matrix 2:\n";
cout << m2 << endl;
cout << "Matrix 1 * Matrix 2\n";
cout << m1 * m2 << endl;
getch();
cout << "Matrix 1 + Matrix 1\n";
cout << m1 + m1 << endl;
getch();
cout << "Matrix 1 - Matrix 1\n";
cout << m1 - m1 << endl;
getch();
cout << "Matrix 1 * 4\n";
cout << m1 * 4 << endl;
getch();
return 0;
}