as suggested on my previous question, C++ simple matrix class, improve coding, I am posting my revised code for feedback. I followed ruds's suggestion about memory management instead of using std::vector. Thanks also to Lstor and Corbin for their help too.
One thing that called my atention is that my program actually runs slower after adding the modifications, before it was running near 128 iterations per second on a single core machine and 382 in a 4-core machine, now it runs at 125 in the single core and 360 in the 4-core machine. I am not sure the way i was managing memory in my first version is faster or I implemented it wrong.
Here is the code:
Grid3d.h:
#ifndef _GRID3D_
#define _GRID3D_
#include <iostream>
class Grid3d
{
private:
size_t M, N, L;
double* buffer;
size_t compute_index(size_t, size_t, size_t) const;
public:
//Constructores
Grid3d(size_t,size_t,size_t);
Grid3d();
Grid3d(const Grid3d&);
~Grid3d();
//Operadores
double& operator()(size_t, size_t, size_t);
double operator()(size_t, size_t, size_t) const;
Grid3d& operator=(Grid3d);
//Acceso
int get_L();
int get_M();
int get_N();
double get(size_t,size_t,size_t) const;
void reset();
};
std::ostream & operator<< (std::ostream &,Grid3d);
#endif
Grid3d.cc:
#include "Grid3d.h"
#include <cmath>
#include <iomanip>
#include <cassert>
using namespace std;
//------------------------------------------------------------------
// Constructores
//------------------------------------------------------------------
//Constructor
Grid3d::Grid3d(size_t M, size_t N, size_t L)
: M(M), N(N), L(L), buffer(new double[M * N * L])
{
for (size_t l=0;l<M*N*L;l++){
buffer[l] = NAN;
}
}
//Constructor vacío
Grid3d::Grid3d()
:M(0), N(0), L(0)
{
buffer = NULL;
}
//Constructor copia
Grid3d::Grid3d(const Grid3d &other)
:M(other.M), N(other.N), L(other.L)
{
buffer = new double[M * N * L];
for (size_t l=0;l<M*N*L;l++){
buffer[l] = other.buffer[l];
}
}
//Destructor
Grid3d::~Grid3d() { delete [] buffer; }
//------------------------------------------------------------------
// Operadores
//------------------------------------------------------------------
//Access operator ():
double& Grid3d::operator()(size_t i, size_t j, size_t k)
{
assert(i >= 0 and i < M);
assert(j >= 0 and j < N);
assert(k >= 0 and k < L);
return buffer[compute_index(i, j, k)];
}
//Access operator () const:
double Grid3d::operator()(size_t i, size_t j, size_t k) const
{
assert(i >= 0 and i < M);
assert(j >= 0 and j < N);
assert(k >= 0 and k < L);
return buffer[compute_index(i, j, k)];
}
//Assignment operator
Grid3d& Grid3d::operator=(Grid3d other)
{
using std::swap;
swap(M, other.M);
swap(N, other.N);
swap(L, other.L);
swap(buffer, other.buffer);
return *this;
}
//------------------------------------------------------------------
// Acceso
//------------------------------------------------------------------
size_t Grid3d::compute_index(size_t i, size_t j, size_t k) const
{
return k * (M * N) + i * N + j;
}
int Grid3d::get_L()
{
return L;
}
int Grid3d::get_M()
{
return M;
}
int Grid3d::get_N()
{
return N;
}
double Grid3d::get(size_t i, size_t j, size_t k) const
{
assert(i >= 0 and i < M);
assert(j >= 0 and j < N);
assert(k >= 0 and k < L);
return buffer[compute_index(i, j, k)];
}
void Grid3d::reset()
{
for (size_t l=0;l<M*N*L;l++){
buffer[l] = NAN;
}
}
//------------------------------------------------------------------
// Others
//------------------------------------------------------------------
//cout
std::ostream & operator << (std::ostream & os , Grid3d g)
{
int M = g.get_M();
int N = g.get_N();
int L = g.get_L();
for (int k=0;k<L;k++){
cout << "k = " << k << endl;
for (int i=0;i<M;i++){
for (int j=0;j<N;j++){
cout.width(10);
os << setprecision(3) << g.get(i,j,k)<< " ";
}
os << endl;
}
os << endl;
}
return os;
}
EDIT: Here is an updated version including your suggestions
Grid3d.h:
#ifndef _GRID3D_
#define _GRID3D_
#include <iostream>
class Grid3d
{
private:
std::size_t M, N, L;
double* buffer;
std::size_t compute_index(std::size_t, std::size_t, std::size_t) const;
public:
//Constructores
Grid3d(std::size_t,std::size_t,std::size_t);
Grid3d();
Grid3d(const Grid3d&);
~Grid3d();
//Operadores
double& operator()(std::size_t, std::size_t, std::size_t);
double operator()(std::size_t, std::size_t, std::size_t) const;
Grid3d& operator=(Grid3d);
//Acceso
std::size_t get_L() const;
std::size_t get_M() const;
std::size_t get_N() const;
double get(std::size_t,std::size_t,std::size_t) const;
void reset();
};
std::ostream & operator<< (std::ostream& ,Grid3d const &);
#endif
Grid3d.cc:
#include "Grid3d.h"
#include <cmath>
#include <iomanip>
#include <cassert>
#include <cstring>
using namespace std;
//------------------------------------------------------------------
// Constructores
//------------------------------------------------------------------
//Constructor
Grid3d::Grid3d(size_t M, size_t N, size_t L)
:M(M), N(N), L(L), buffer(new double[M * N * L])
{
reset();
}
//Default Constructor
Grid3d::Grid3d()
:M(0), N(0), L(0)
{
buffer = NULL;
}
//Copy constructor
Grid3d::Grid3d(const Grid3d &other)
:M(other.M), N(other.N), L(other.L)
{
double* tmp = new double[M * N * L];
//delete [] buffer; <-- this line gives me a "core generated" error
buffer = tmp;
std::memcpy(buffer, other.buffer, M * N * L * sizeof(double));
}
//Destructor
Grid3d::~Grid3d() { delete [] buffer; }
//------------------------------------------------------------------
// Operators
//------------------------------------------------------------------
//Access operator ():
double& Grid3d::operator()(size_t i, size_t j, size_t k)
{
assert(i >= 0 and i < M);
assert(j >= 0 and j < N);
assert(k >= 0 and k < L);
return buffer[compute_index(i, j, k)];
}
//Access operator () const:
double Grid3d::operator()(size_t i, size_t j, size_t k) const
{
assert(i >= 0 and i < M);
assert(j >= 0 and j < N);
assert(k >= 0 and k < L);
return buffer[compute_index(i, j, k)];
}
//Assignment operator
Grid3d& Grid3d::operator=(Grid3d other)
{
using std::swap;
swap(M, other.M);
swap(N, other.N);
swap(L, other.L);
swap(buffer, other.buffer);
return *this;
}
//------------------------------------------------------------------
// Access Operator
//------------------------------------------------------------------
size_t Grid3d::compute_index(size_t i, size_t j, size_t k) const
{
return k * (M * N) + i * N + j;
}
size_t Grid3d::get_L() const
{
return L;
}
size_t Grid3d::get_M() const
{
return M;
}
size_t Grid3d::get_N() const
{
return N;
}
double Grid3d::get(size_t i, size_t j, size_t k) const
{
assert(i >= 0 and i < M);
assert(j >= 0 and j < N);
assert(k >= 0 and k < L);
return buffer[compute_index(i, j, k)];
}
void Grid3d::reset()
{
for (size_t l=0;l<M*N*L;l++){
buffer[l] = NAN;
}
}
//------------------------------------------------------------------
// Others
//------------------------------------------------------------------
//cout
std::ostream& operator<<(std::ostream& os , Grid3d const & g)
{
size_t M = g.get_M();
size_t N = g.get_N();
size_t L = g.get_L();
for (size_t k=0;k<L;k++){
cout << "k = " << k << endl;
for (size_t i=0;i<M;i++){
for (size_t j=0;j<N;j++){
os.width(10);
os << setprecision(3) << g.get(i,j,k)<< " ";
}
os << "\n";
}
os << "\n";
}
std::cout << std::flush;
return os;
}