How can I change the following code such that I can use new
and delete
instead of malloc
and free
?
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
class myclass{
private:
float **m_R;
public:
myclass();
~myclass();
float **getR(void);
void setR(void);
};
myclass::myclass()
{
// first allocate rows (for pointers)
m_R = (float**)malloc(3*sizeof(float));
// next allocate columns for float values
for(int i=0;i<3;i++)
*(m_R+i) = (float*)malloc(3*sizeof(float));
}
myclass::~myclass()
{
// first free memory allocated by columns
for(int i = 0; i < 3; i++)
{
free(m_R[i]);
}
// next free memory allocated by rows
free(m_R);
}
void myclass::setR(void)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
m_R[i][j] = 10*i+j;
//cout << m_R[i][j] << ", ";
}
//cout << "\n";
}
}
float **myclass::getR(void)
{
return m_R;
}
int main () {
myclass obj;
obj.setR();
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%02d, ",(int)obj.getR()[i][j]);
}
cout << "\n";
}
return 0;
}
Edit1: Please note that I have to use a function (not written by me) which takes float**
as argument and I have no choice (such as vector
) than using float**
.
Edit2: The function is from Proximity Query Package (PQP) written as following:
int
PQP_Distance(PQP_DistanceResult *result,
PQP_REAL R1[3][3], PQP_REAL T1[3], PQP_Model *o1,
PQP_REAL R2[3][3], PQP_REAL T2[3], PQP_Model *o2,
PQP_REAL rel_err, PQP_REAL abs_err,
int qsize = 2);
T* a = (T*)malloc(sizeof(T))
becomesnew T
.T* b = (T*)malloc(N * sizeof(T))
becomesnew T[N]
.free(a)
becomesdelete a
.free(b)
becomesdelete[] b
.
So you get:
myclass::myclass()
{
// first allocate rows (for pointers)
m_R = new float*[3];
// next allocate columns for float values
for(int i=0;i<3;i++)
*(m_R+i) = new float[3];
}
myclass::~myclass()
{
// first free memory allocated by columns
for(int i = 0; i < 3; i++)
{
delete[] m_R[i];
}
// next free memory allocated by rows
delete [] m_R;
}
Note that this is actually not very optimal. If you want 3x3 matrices, you're better off allocating 9 floats in one block.
Also note that your C is incorrect.
m_R = (float**)malloc(3*sizeof(float));
should be
m_R = (float**)malloc(3*sizeof(float*));
Your code probably "works" because you're compiling for 32-bit, where float
and float*
are 4 bytes. On a 64 bit build, float*
is 8 bytes.
Honestly, though, since your dimensions are fixed and small, you should store everything in the object itself:
class myclass{
private:
float m_R[3][3];
public:
myclass() {}
~myclass() {}
void setR(void);
float* operator[](unsigned i) { return m_R[i]; }
const float* operator[](unsigned i) const { return m_R[i]; }
};
void myclass::setR(void)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
(*this)[i][j] = 10*i+j;
//cout << (*this)[i][j] << ", ";
}
//cout << "\n";
}
}
int main () {
myclass obj;
obj.setR();
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%02d, ",(int)(obj[i][j]));
}
cout << "\n";
}
return 0;
}
This is how I usually do it, so I get the readability of [][] with the efficiency of in-object storage.
Assuming that using the standard C++ library is an option, you should use
std::vector<std::vector<float> > m_R;
instead of float**
. There is absolutely no downside, and you would get many convenient things for free. For example, you would be able to find the size of the vector and each of its dimensions without passing a pair of numbers on the side, or coding in some assumptions. You would be able to allocate without loops, and delete with no code at all.
If this is not an option, you can replace malloc
/free
with new[]
/delete[]
as follows:
// Creating
float **m_R = new float*[10];
for (int i = 0 ; i != 10 ; i++) {
m_R[i] = new float[20];
}
// Deleting
for (int i = 0 ; i != 10 ; i++) {
delete[] m_R[i];
}
delete[] m_R;
You should decide if you want to program in C (hence, no classs) or C++ (hence, no plain C, when C++ library exist).
Right now you just have C + some classes.
Respect to what you did (a class who wraps a bidimensional fixed array) a more proper way can be this:
#include <iostream>
#include <iomanip>
#include <cassert>
class myclass
{
public:
mycalss() :m() {}
float& at(size_t r, size_t c)
{ return m[r][c]; }
const float& at(size_t r, size_t c) const
{ return m[r][c]; }
void setR()
{
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
m[i][j] = 10*i+j;
}
private:
float m[3][3];
};
int main ()
{
using namespace std;
myclass obj;
obj.setR();
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
cout << setw(2) << obj.at(i,j) << endl;
return 0;
}
Note that there is no need to use dynamic memory.
If you want to use dynamic memory(may be because the array size should be bigger) you can rely on std::vector as a container:
#include <iostream>
#include <iomanip>
#include <vector>
#include <cassert>
class myclass
{
public:
mycalss(unsigned rows_, unsigned cols_) :m(), rows(rows_), cols(cols_)
{ m.resize(rows_*cols_); }
float& at(size_t r, size_t c)
{ return m[r*cols+c]; }
const float& at(size_t r, size_t c) const
{ return m[r*cols+c]; }
void setR()
{
for(int i=0;i<rows;i++)
for(int j=0;j<cols;j++)
at(i,j) = 10*i+j;
}
private:
std::vector<float> m;
size_t rows, cols;
};
int main ()
{
using namespace std;
static const size_t R=4, C=4;
myclass obj(R,C);
obj.setR();
for(int r=0;r<R;r++)
for(int c=0;c<C;c++)
cout << setw(2) << obj.at(r,c) << endl;
return 0;
}
来源:https://stackoverflow.com/questions/12675416/how-to-replace-malloc-and-free-with-new-and-delete