Destructor and overloaded= operator for Image class - c++

I am new in C++. I have a problem with Image Processing. What I am trying to do is to write my class Image, which has as private variables horizontal and vertical sizes of an image and data for each pixel (grayscale, just 2D array of floats). I also wrote basic functions within the class: getPixel,SetPixel, GetSize, GetData (returns 2D array of data).
My question is: I read, that for best performance I have to write a destructor function and overloaded "=" operator at least.
1) Can someone explain why I really need it (as long as this version working more or less).
2) Can you write destructor and "=" operator for me? I guess, it is not difficult for experts, I tried once but with my destructor I got memory errors: Error _BLOCK_TYPE_IS_VALID(pHead->nBlockUse);
Update: Even now, without defining "=" operator, I can use it in my main function. If, say, I had Image img1 of size (1x1) and img2 of size (2x2), I can write img1=img2, and it works!
Update2: After I tried to implement simple destructor (delete [] pix) the error "_BLOCK_TYPE_IS_VALID" appeared
struct Pixel
{
float p;
};
struct size
{
int x;
int y;
};
class Image {
private:
int _x, _y;
Pixel *pix;
public:
Image(int x, int y){
pix = new Pixel[x * y];
_x = x;
_y = y;
}
float getPixel(int i, int j) {
return pix[i * _y + j].p;
}
void setPixel(int i, int j, Pixel val)
{
pix[i * _y + j].p = val.p;
}
size GetSize(){
size a;
a.x = _x;
a.y = _y;
return a;
}
Pixel **GetData(){
Pixel **a=0;
a = new Pixel*[_x];
for (int i = 0; i < _x; i++){
a[i] = new Pixel[_y];
for (int j = 0; j < _y; j++){
a[i][j] = pix[i*_y + j];
}
}
return a;
}
};
UPDDATE 3: I tried to implement everything from rule of three. I added:
~Image()
{
delete[] pix;
}
Image(const Image& that)
{
pix = new Pixel[that._x*that._y];
pix = that.pix;
_x = that._x;
_y = that._y;
}
Image& operator=(const Image& that)
{
if (this != &that)
{
delete[] pix;
pix = new Pixel[that._x*that._y];
pix = that.pix;
_x = that._x;
_y = that._y;
}
return *this;
}
Still got memory error: "_BLOCK_TYPE_IS_VALID..."

You asked:
1) Can someone explain why I really need it (as long as this version working more or less).
You are allocating memory for pix in the constructor. You need to implement a destructor that deallocates the memory. I don't see one implemented in your class.
~Image()
{
delete [] pix;
}
As soon as you add code in the destructor for releasing resources that were acquired by the class at some point in its life time, The Rule of Three comes into play and you'll have to implement the copy constructor and assignment operator for a bug free code.
The assignment operator will look something like:
Image& operator=(Image const& rhs) {
// Don't do anything for self assignment, such as a = a;
if ( this != &rhs )
{
delete [] pix;
_x = rhs._x;
_y = rhs._y;
pix = new Pixel[_x * _y];
for ( int i = 0; i < _x*_y; ++i )
{
pix[i] = rhs.pix[i]
}
}
return *this;
}

1) Can someone explain why I really need it (as long as this version working more or less).
Is already answered here: https://stackoverflow.com/a/4172724/2642059
The segment that pertains to you is:
Most of the time, you do not need to manage a resource yourself, because an existing class such as std::string already does it for you. Just compare the simple code using a std::string member to the convoluted and error-prone alternative using a char* and you should be convinced. As long as you stay away from raw pointer members, the rule of three is unlikely to concern your own code.
As a new C++ coder the best thing I can do for you is steer you away from raw pointers.
2) Can you write destructor and "=" operator for me? I guess, it is not difficult for experts, I tried once but with my destructor I got memory errors: Error _BLOCK_TYPE_IS_VALID(pHead->nBlockUse);
R Sahu's answer does a good job of this. But I'd advise you to get rid of your raw pointer instead, so I'll show you how to do that:
struct Pixel
{
Pixel() : p(0.0f) {} // Create a default constructor for Pixel so it can be used in a vector
float p;
};
class Image {
private:
int _x, _y;
std::vector<Pixel> pix; // This is your new array
public:
Image(int x, int y) :
pix(x * y) // This is called the constructor initializer list and that's where you construct member objects.
{
_x = x;
_y = y;
}
float getPixel(int i, int j) {
return pix[i * _y + j].p;
}
void setPixel(int i, int j, Pixel val)
{
pix[i * _y + j].p = val.p;
}
size GetSize(){
size a;
a.x = _x;
a.y = _y;
return a;
}
const Pixel* GetData(){ // We're going to pass back the vector's internal array here, but you should probably just return a const vector
return pix.data(); // We're returning this as read only data for convenience any modification to the data should be done through the Image class
}
};

Related

How to construct base class multiple times in derived constructor

Hello I I have problem on my assignment which I need to init base constructor which is point multiple time in derived constructor which is polygon.
The polygon have at least 3 point , each point have a coordinate value. any one have ideas how to init base constructor multiple time in constructor init?
The inheritance ideas is not my ideas , is the assignment question.
this is the question
Polygon  (constructor) creates a polygon with npoints vertices, the vertices take their values from those stored in the array points. Note that the array points should not be assumed to persist; it may be deleted after the constructor is invoked.
struct PointType
{
float x;
float y;
};
class Point
{
public:
Point(const PointType& center );
virtual ~Point();
private:
PointType m_center;
};
class Polygon : public Point
{
public:
Polygon(const PointType* points, int npoints);
~Polygon();
const VectorType& operator[](int index) const;
private:
int m_npoints;
Object::PointType * m_pt;
};
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include "Object.hpp"
using namespace std;
const float eps = 1e-5f;
bool Near(float x, float y)
{
return abs(x-y) < eps;
}
float frand()
{
return 10.0f*float(rand())/float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0,
max_count = 0;
// Polygon tests
int n = 3 + rand()%8;
float *xs = new float[n],
*ys = new float[n];
float x = 0, y = 0;
PointType *Ps = new PointType[n];
for (int i=0; i < n; ++i) {
xs[i] = frand(), ys[i] = frand();
Ps[i] = PointType(xs[i],ys[i]);
x += xs[i], y += ys[i];
}
}
Point::Point(const PointType& center)
: m_center{center}
{
}
// this is wrong, can correct me how to construct it?
Polygon::Polygon(const PointType* points, int npoints, float depth)
:m_npoints{npoints} , m_pt{new Object::PointType[npoints]}, Point (*m_pt ,depth)
{
for(int i=0; i < m_npoints ; ++i)
{
m_pt[i] = points[i];
}
}
enter code here
this the assignment structure like
enter image description here
I took away other object class implementation
Your assignment text doesn't say anything about inheritance. It essentially describes composition. Go from here:
class Polygon
{
public:
// constructor should allocate the array
Polygon(const PointType* points, int npoints);
~Polygon();
private:
Point *m_npoints; // or use smart pointer if you're allowed to.
};
It is a trick question, is actually want me to find centroid point of polygon.
So I need a private compute center point of polygon function and return the result of center point of polygon, and then call the function in point constructor when init.

Debug Assertion failed on making copy constructor

I am trying to make a copy constructor because I have a pointer in my class. However, I got runtime error "Debug Assertion failed" and I do not know what to do. I have two classses, MyMatrix and MyImage. I want to write a copy constructor for MyImage, therefore I also write one for MyMatrix.
class MyMatrix{
private:
unsigned _width, _height;
unsigned char *_data;
public:
MyMatrix(MyMatrix &other);
}
MyMatrix::MyMatrix(MyMatrix &other) {
_width = other._width;
_height = other._height;
_data = new unsigned char[_width*_height];
memcpy(_data, other._data, _width*_height*sizeof(unsigned char));
}
class MyImage {
public:
int _width;
int _height;
MyMatrix _Y; //gray level
}
MyImage::MyImage(MyImage &other) {
_width = other._width;
_height = other._height;
_Y = MyMatrix(other._Y);
}
int main(){
char *filename = "hw1_images/p1/house.raw"; //some raw image
int width = 512;
int height = 512;
//read the image
MyImage inputImage(filename, width, height, fileMode::CFA);
//copy the image
MyImage test(inputImage);
return 0;
}
I got error even if I comment the memcry(). If I use std::cout to display the value of my copy, it is alway 221. Please help me with it. Thank you.
You are writing _Y = MyMatrix(other._Y);, I expect that you have defined the assignement operator for your Matrix class : MyMatrix & operator(const MyMatrix & other); otherwise the compiler will create a default one for you that just copy your attributes, meaning your pointer will be copied, not the content.
And, as I see that you can manipulate an important size of data and if you have c++11 enabled, I would definitely look at the copy swap idiom : What is the copy-and-swap idiom?
If its just matter of crash then you may do something like below.
class MyMatrix{
private:
unsigned _width, _height;
unsigned char *_data;
public:
MyMatrix(){
_width = 2;
_height = 3;
_data = new unsigned char[sizeof(unsigned char)];
}
MyMatrix(MyMatrix &other);
};
MyMatrix::MyMatrix(MyMatrix &other) {
_width = other._width;
_height = other._height;
_data = new unsigned char[(_width*_height) + 1];
memcpy(_data, other._data, _width*_height*sizeof(unsigned char));
}

Declaring object onto the stack in class definition vs in constructor

When I declare the "Level" object in the "LevelEditor" class definition like so, everything works fine:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
}
//...
private:
//...
Level level = Level(50, 50);
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
But when I declare the "Level" object in the "LevelEditor" constructor like so, I get a stack overflow:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
//NOTE: width and height both equal 50
level = Level(width, height);
}
//...
private:
//...
Level level;
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
This makes me wonder what the difference is between declaring a variable in the class definition and in the constructor is besides the fact of the time of defining the variable. Any idea of what the cause could be? and how I could declare the "Level" object in the constructor without having to put anything on the heap?
EDIT:
"Level" class definition in case it is helpful:
class Level
{
public:
Level(int w, int h)
{
Worldwidth = w;
Worldheight = h;
for (unsigned int y = 0; y < Worldheight; y++)
{
for (unsigned int x = 0; x < Worldwidth; x++)
{
grid[x][y] = -1;
}
}
}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
int grid[300][300];
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
There are several issues with your code. I will try to address the stack overflow error. The other issue is that your Level class is not safely copyable -- that can be taken care of by utilizing smart pointers such as std::unique_ptr and std::shared_ptr.
First, your classes use 300 x 300 arrays of T, in one case, T is a WorldSprite* the other is int. Arrays this size declared as members will balloon the size of each of your objects that contain them to hundreds of kilobytes in size. This will at some point take a toll on the stack.
So you should remove these definitions, and instead use std::vector.
#include <vector>
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader) :
tile(w,std::vector<WorldSprite*>(h))
editing(true), width(w), height(h)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y,
tileWidth, tileHeight, shader);
}
level = Level(width, height);
}
private:
Level level;
int width, height;
std::vector<std::vector<WorldSprite*>> tile;
bool editing;
};
Here is the Level class with the same type of changes:
#include <vector>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int> >grid;
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
Note that the vector replaces the array, and it will use heap memory to initialize. In the Level class, we initialize the vector and set all the entries to -1 in one single call of the vector's constructor.
The reason why this will not hike the size of your objects to very high amounts is that vector will create its data on the heap (unless you have some sort of custom allocator that gets the memory from another source). Thus the size of your classes will be reasonable (probably less than 100 bytes).
The other issue is that your Level class is not safely copyable (neither is the LevelEditor, but I will leave it alone, as the same set of changes can be done).
The problem will be this line:
level = Level(width, height);
The problem with this line is that the assignment operator will be called and the copy constructor may be called. If you look at your Level class, it has a destructor that removes all the pointers from the vectors that contain pointers. This will be disastrous if you copy Level objects, since you will be destroying all of your data due to temporaries being destroyed.
If there is no sense of which Level actually owns the pointers, and it comes down to "whoever is the last man standing is the owner", and you will actually be sharing pointers between Level instances (that's why it's called shared_ptr) then you can use this solution:
#include <vector>
#include <memory>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int>> grid;
std::vector<std::shared_ptr<Tile>> tiles;
std::vector<std::shared_ptr<Entity>> entities;
};
Note how there is no destructor code -- there need not be any. The deletion is all done by the shared_ptr, so there is no work for you to do -- everything is managed. What will happen is that the last Level that gets destroyed that you shared the pointers with will do the actual deletion. So when this line is done
level = Level(width, height);
the copying of the Level objects bumps up and down the internal shared_ptr's reference count, leaving you with a reference count of 1 (that is the final level on the left-hand side of the = sign).
See here for usage of std::shared_ptr: http://en.cppreference.com/w/cpp/memory/shared_ptr
Please note that you may want to use std::unique_ptr if ownership is an issue. I suggest you search SO for usages of std::unique_ptr. I showed you std::shared_ptr since it is the most straightforward at this point (but again, may not suit all your needs - YMMV).

c++ vector of non-pointers

I have a TileMap class that has a std::vector<Tile>. While just generating the vector, i notice that the Tiles are getting deleted shortly after creation, thus not letting the TileMap class do anything with them.
TileMap is a kind of information class that will be used by a Stage class for various things, so it will need to access TileMap.tiles() (which returns the mTiles_ TileMap.
TileMap constructor:
TileMap::TileMap(std::vector<int> pTiles, int pWidth):mWidth_(pWidth)
{
for(int i = 0; i < pTiles.size(); i++)
{
int x = (i % mWidth_);
int y = floorf(i / mWidth_);
Tile tile((Tile::TileType)pTiles[i]);
tile.x = x;
tile.y = y;
tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
mTiles_.push_back(tile);
}
}
Previously it was a std::vector<std::shared_ptr<Tile>> but i was seeing if i could get around using pointers. Is there a way to do this?
EDIT: Tile definition added -
class Tile : public SquareCollidableObject
{
public:
enum TileType {
TILE_GRASS,
TILE_OUTSIDE_WALL_TOP_LEFT_OUTER,
TILE_OUTSIDE_WALL_TOP,
TILE_OUTSIDE_WALL_TOP_RIGHT_OUTER,
TILE_OUTSIDE_WALL_LEFT,
TILE_OUTSIDE_WALL_RIGHT,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_OUTSIDE_WALL_BOTTOM,
TILE_OUTSIDE_WALL_TOP_RIGHT_INNER,
TILE_OUTSIDE_WALL_TOP_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_WALL,
TILE_INSIDE_WALL_TOP_LEFT_INNER,
TILE_INSIDE_WALL_TOP,
TILE_INSIDE_WALL_TOP_RIGHT_INNER,
TILE_INSIDE_WALL_LEFT,
TILE_INSIDE_WALL_RIGHT,
TILE_INSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_INSIDE_WALL_BOTTOM,
TILE_INSIDE_WALL_TOP_RIGHT_OUTER,
TILE_INSIDE_WALL_TOP_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_FLOOR
};
Tile(TileType);
virtual ~Tile();
virtual void update(float);
virtual void draw(sf::RenderWindow&, sf::Vector2f);
TileType tileType;
static int TILE_WIDTH;
static int TILE_HEIGHT;
int x;
int y;
// pathfinding
std::shared_ptr<Tile> previousTile;
float g; // cost to tile (total cost from previous tiles + cost to this tile)
float h; // cost to next tile
float f; // g + h
bool walkable;
};
Tile needs to have a copy (or move) constructor and assignment operator for use with std::vector.
nTiles_.push_back(tile) copy-constructs a new Tile object from the local tile.
In that for loop, at each iteration, the local object tile gets constructed, then a copy gets pushed into the vector, and then the local tile gets destructed. This is why destructors get called during the for loop.
One way to avoid this and instead only construct the Tile object that will be in the vector, you could write
TileMap::TileMap(std::vector<int> pTiles, int pWidth):mWidth_(pWidth)
{
for(int i = 0; i < pTiles.size(); i++)
{
int x = (i % mWidth_);
int y = floorf(i / mWidth_);
mTiles_.emplace_back( (Tile::TileType)pTiles[i] );
Tile& tile = mTiles_.back();
tile.x = x;
tile.y = y;
tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
}
}
emplace_back takes the arguments of the Tile constructor, and constructs an object in-place at the end of the vector. back returns a reference to the last item.
If Tile objects are heavy-weight (i.e. copying them is expensive), it may be better to use pointers instead as before, or implement move-constructor and move-assignment operator. std::vector will copy (or move) its items if new items get inserted/erased, or when the vector gets resized.
Also the tiles() function needs to return the vector by reference.
There is 2 reasons of Tile destruction in your code:
The local variable that you copy inside vector, and the internal copy when vector resizes internal memory.
To avoid the former, you have to emplace back the new element; for the later, you have to reserve place in vector. It results in something like:
TileMap::TileMap(const std::vector<int>& pTiles, int pWidth) : mWidth_(pWidth)
{
mTiles_.reserve(pTiles.size());
for(int i = 0; i != pTiles.size(); ++i)
{
const int x = i % mWidth_;
const int y = i / mWidth_;
mTiles_.emplace_back(static_cast<Tile::TileType>(pTiles[i]));
Tile& tile = mTiles_.back();
tile.x = x;
tile.y = y;
tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
}
}
First of all, your TileMap constructor calls .position which isn't a member of the Tile class.
Secondly, #tmlen's answer looks like it works as expected to me. If I run this code:
#include <stdlib.h>
#include <memory>
#include <vector>
#include <iostream>
using namespace std;
class Tile
{
public:
enum TileType {
TILE_GRASS,
TILE_OUTSIDE_WALL_TOP_LEFT_OUTER,
TILE_OUTSIDE_WALL_TOP,
TILE_OUTSIDE_WALL_TOP_RIGHT_OUTER,
TILE_OUTSIDE_WALL_LEFT,
TILE_OUTSIDE_WALL_RIGHT,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_OUTSIDE_WALL_BOTTOM,
TILE_OUTSIDE_WALL_TOP_RIGHT_INNER,
TILE_OUTSIDE_WALL_TOP_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_WALL,
TILE_INSIDE_WALL_TOP_LEFT_INNER,
TILE_INSIDE_WALL_TOP,
TILE_INSIDE_WALL_TOP_RIGHT_INNER,
TILE_INSIDE_WALL_LEFT,
TILE_INSIDE_WALL_RIGHT,
TILE_INSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_INSIDE_WALL_BOTTOM,
TILE_INSIDE_WALL_TOP_RIGHT_OUTER,
TILE_INSIDE_WALL_TOP_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_FLOOR
};
Tile(TileType t):
tileType(t)
{
cout << "Constructing tile\n";
}
virtual ~Tile()
{
cout << "Destructing tile\n";
}
TileType tileType;
static int TILE_WIDTH;
static int TILE_HEIGHT;
int x;
int y;
// pathfinding
std::shared_ptr<Tile> previousTile;
float g; // cost to tile (total cost from previous tiles + cost to this tile)
float h; // cost to next tile
float f; // g + h
bool walkable;
};
class TileMap
{
int mWidth_;
std::vector<Tile> mTiles_;
public:
TileMap(const std::vector<int>& pTiles, int pWidth) : mWidth_(pWidth)
{
mTiles_.reserve(pTiles.size());
for (int i = 0; i != pTiles.size(); ++i)
{
const int x = i % mWidth_;
const int y = i / mWidth_;
mTiles_.emplace_back(static_cast<Tile::TileType>(pTiles[i]));
Tile& tile = mTiles_.back();
tile.x = x;
tile.y = y;
//tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> tiles;
tiles.push_back(Tile::TileType::TILE_GRASS);
cout << "Creating tilemap\n";
TileMap t(tiles, tiles.size());
cout << "Tilemap created\n";
cout << "Exiting\n";
return 0;
}
I get the following result:
Creating tilemap
Constructing tile
Tilemap created
Exiting
Destructing tile

How to write destructor to be able to compile the code and free all allocated memory?

I've created custom class, that shall behave like a matrix. I've got there some basic operations and everything seems to be working well... Nevertheless, I can't find out, what shall I write to destructor of this class to free all allocated memory. Would you please advice me?
class CMatrix {
public:
class Proxy {
friend class CMatrix;
const CMatrix* cmat;
CMatrix *matrix;
size_t n;
Proxy(const CMatrix& m, size_t i)
: cmat(&m), matrix(), n(i) {
}
Proxy(CMatrix& m, size_t i)
: cmat(&m), matrix(&m), n(i) {
}
public:
const double& operator[](size_t j) const {
return cmat->_arrayofarrays[n * cmat->y + j];
}
double& operator[](size_t j) {
if (matrix) {
return matrix->_arrayofarrays[n * cmat->y + j];
} else return cmat->_arrayofarrays[cmat->y];
}
};
const Proxy operator[](size_t i) const {
return Proxy(*this, i);
}
Proxy operator[](size_t i) {
return Proxy(*this, i);
}
CMatrix() {
_arrayofarrays = NULL;
x = 0;
y = 0;
};
// constructor
CMatrix(size_t x, size_t y) : _arrayofarrays(), x(x), y(y) {
_arrayofarrays = new double[ x * y ]();
}
// destructor
~CMatrix() {
// ?!?!???!?!?!?!!!!?!?!?
// #$#%#^$!!!!#$#%!!
}
// copy constructor
CMatrix(const CMatrix& other) : _arrayofarrays(), x(other.x), y(other.y) {
delete [] _arrayofarrays;
_arrayofarrays = new double[x * y];
if (_arrayofarrays)
std::copy(other._arrayofarrays, other._arrayofarrays + (x * y), _arrayofarrays);
}
CMatrix& operator =(const CMatrix& rval) {
delete [] _arrayofarrays;
_arrayofarrays = new double[ rval.x * rval.y];
std::copy(rval._arrayofarrays, rval._arrayofarrays + (rval.x * rval.y), _arrayofarrays);
x = rval.x;
y = rval.y;
return *this;
}
double *_arrayofarrays;
size_t x;
size_t y;
};
EDIT:
actually now I've realized, that it crashes after running this part of code. Before calling this code, I have there a instances of my class, let's call it a,b,c and then I want to set a = b-c;
this works well for the first time...but when I want to repeat it, then it crashes
CMatrix CMatrix::operator-(const CMatrix &matrix) const {
if (this->x != matrix.x || this->y != matrix.y) {
throw CSizeException(matrix.y, matrix.x, this->y, this->x, '+');
};
CMatrix m(this->x, this->y);
CMatrix l(matrix.x, matrix.y);
l._arrayofarrays = this->_arrayofarrays;
CMatrix o(matrix.y, matrix.y);
o = matrix;
CMatrix result(this->x, this->y);
for (unsigned int i = 0; i < this->x; i++)
for (unsigned int j = 0; j < this->y; j++)
m[i][j] = l[i][j] - o[i][j];
return m;
}
Something like this?
~CMatrix() {
delete[] _arrayofarrays;
}
All arrays allocated with new[] must be destroyed by a matching call to delete[]. Moreover, you can remove the delete[] statement from the copy constructor:
CMatrix(const CMatrix& other) : _arrayofarrays(), x(other.x), y(other.y) {
// delete [] _arrayofarrays;
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// This is unnecessary: you are creating a new object, so this data member
// is not pointing to any previously allocated array
// ...
}
UPDATE:
(from the comments) I can't use this code... _arrayofarrays is actually 2D array, so this causes that running of the program fails..probably segfault
This is incorrect: _arrayofarrays is a 1D array, and calling delete[] is the proper way do destroy it. If doing so leads to a segfault, probably you're doing something wrong in the rest of your code.
As an advice, it is usually a good idea to avoid manual memory management through raw pointers, new, and delete (or their array counterparts), because it is error-prone and easily leads to memory leaks or dereferencing of invalid pointers/reference.
Consider using standard containers such as std::vector<> or std::deque<> instead.
EDIT:
In the code of operator - you are doing:
l._arrayofarrays = this->_arrayofarrays;
This way you are having two matrix objects which encapsulate the same array: therefore, deleting one of the two will make the other one invalid as well. This is probably the root cause of your problem.
Also, you are creating way too many temporaries in there. Unless I'm missing something, this should be enough:
CMatrix CMatrix::operator-(const CMatrix &matrix) const {
if (this->x != matrix.x || this->y != matrix.y) {
throw CSizeException(matrix.y, matrix.x, this->y, this->x, '+');
};
CMatrix result(this->x, this->y);
for (unsigned int i = 0; i < this->x; i++)
for (unsigned int j = 0; j < this->y; j++)
result[i][j] = (*this)[i][j] - matrix[i][j];
return result;
}
The way to delete the memory in the destructor is the same as you wrote it in the other member functions:
delete [] _arrayofarrays;
If this crashes then you must be corrupting memory somewhere else. Try using valgrind to check for memory errors.
There are some problems with your copy constructor:
CMatrix(const CMatrix& other) : _arrayofarrays(), x(other.x), y(other.y) {
delete [] _arrayofarrays;
This is useless, there's nothing to delete yet.
_arrayofarrays = new double[x * y];
if (_arrayofarrays)
This if is useless, new will either throw an exception or return a non-null pointer, so checking if it's null is useless.
std::copy(other._arrayofarrays, other._arrayofarrays + (x * y), _arrayofarrays);
}
There are some problems with your assignment operator too:
CMatrix& operator =(const CMatrix& rval) {
delete [] _arrayofarrays;
_arrayofarrays = new double[ rval.x * rval.y];
If the new allocation throws an exception then you leave _arrayofarrays holding a dangling pointer, you should either allocate the new memory before deleting the old memory or zero the old pointer after using delete[]