【问题标题】:How to replace 'malloc' and 'free' with 'new' and 'delete'?如何用“new”和“delete”替换“malloc”和“free”?
【发布时间】:2023-04-04 09:45:01
【问题描述】:

如何更改以下代码,以便可以使用newdelete 而不是mallocfree

#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:请注意,我必须使用一个以float** 作为参数的函数(不是我写的),我别无选择(例如vector),只能使用float**

Edit2:该函数来自Proximity Query Package (PQP),编写如下:

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);

【问题讨论】:

  • 简单回答:不要。用适当的容器替换它们。
  • 你想拿一些非常糟糕的东西,然后用稍微好一点的东西来代替它吗?专业提示:不要。
  • 使用矢量或附近。您的代码仅为 32 位(巧合)。您使用 sizeof(float) 而不是 sizeof(float *) 分配 3 个 float * 的数组,这仅适用于 32 位系统。在 64 位系统上,它只会为您提供所需的一半内存。
  • 采用float** 的“必须使用”的函数的前置/后置条件是什么。我敢打赌,他们可以在仍然使用适当的容器时遇到。
  • 矢量在这里真的不合理,除了作为拐杖,因为尺寸很小且固定。 C++ 容器并非被发明为比程序员更聪明。如果看起来是这样,那不是容器的错。

标签: c++ malloc new-operator


【解决方案1】:
  • T* a = (T*)malloc(sizeof(T)) 变为 new T
  • T* b = (T*)malloc(N * sizeof(T)) 变为 new T[N]
  • free(a) 变为 delete a
  • free(b) 变为 delete[] b

所以你得到:

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;
}

请注意,这实际上不是非常理想的。如果你想要 3x3 矩阵,你最好在一个块中分配 9 个浮点数。

还要注意你的 C 是不正确的。

m_R = (float**)malloc(3*sizeof(float));

应该是

m_R = (float**)malloc(3*sizeof(float*));

您的代码可能“有效”,因为您正在编译 32 位,其中 floatfloat* 是 4 个字节。在 64 位构建中,float* 为 8 个字节。


不过,老实说,由于您的尺寸是固定的且很小,您应该将所有内容存储在对象本身中:

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;
}

这是我通常的做法,因此我获得了 [][] 的可读性和对象内存储的效率。

【讨论】:

  • 非常感谢!这正是我正在寻找的答案......顺便说一句,你是对的!我第一次分配错了,一定是你说的。
  • 您更新的代码对我来说似乎好多了,谢谢。 (有错别字:m_r[i]必须是m_R[i]
  • 谢谢,这很有帮助。我有一个后续问题,如何替换calloc
【解决方案2】:

假设使用标准 C++ 库是一种选择,您应该使用

std::vector<std::vector<float> > m_R;

而不是float**。绝对没有缺点,你会免费得到很多方便的东西。例如,您将能够找到向量的大小及其每个维度,而无需在旁边传递一对数字,或在某些假设中进行编码。您将能够在没有循环的情况下进行分配,并且完全无需代码即可删除。

如果这不是一个选项,您可以将malloc/free 替换为new[]/delete[],如下所示:

// 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;

【讨论】:

    【解决方案3】:

    您应该决定是用 C(因此,没有类)还是 C++(因此,当存在 C++ 库时,没有纯 C)编程。

    现在你只有 C + 一些类。

    尊重你所做的(包装二维固定数组的类) 更合适的方法是:

    #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;
    }
    

    注意,不需要使用动态内存。

    如果你想使用动态内存(可能是因为数组大小应该更大) 你可以依赖 std::vector 作为容器:

    #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;
    }
    

    【讨论】:

    • 感谢您的解释和纯C++代码。我可以从你的代码中学习如何更好地实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2016-04-28
    • 2011-12-19
    相关资源
    最近更新 更多