删除嵌套函数调用中生成的中间指针的最佳做法是什么?

What is the best practice to delete intermediate pointers generated in nested function calls?

我正在用c写一个基本的矩阵库,矩阵数据结构是这样的:

typedef struct Matrix{
    int rows;
    int cols;
    double complex *matrix;
} Matrix;

以及相应的初始化矩阵的函数和释放指针的函数(类似于c++中的构造函数和析构函数)

Matrix* InitializeMatrix(int r, int c){
    Matrix* mat = malloc(sizeof(Matrix));
    mat->rows = r;
    mat->cols = c;
    mat->matrix = (double complex *)malloc(r * c * sizeof(double complex));
    return mat;
}

int DeleteMatrix(Matrix *mat){
    mat->rows = 0;
    mat->cols = 0;
    free(mat->matrix);
    mat->matrix = 0;
    return 0;
}

这里是主要问题。假设我有两个函数

Matrix* fun1(Matrix* input){
    //some operations
    Matrix* mat = InitializeMatrix(r, c);
    //some operations
    return mat;
}
Matrix* fun2(Matrix* input){
    //some operations
    Matrix* mat = InitializeMatrix(r, c);
    //some operations
    return mat;
}

现在我有另一个函数想要嵌套fun1fun2

Matrix* fun3(Matrix* input){
    return fun2(fun1(input));
}

通常当我调用一个函数时,我将不得不调用DeleteMatrix来释放内存,但是在fun2(fun1(input))中,对fun1(input)生成的矩阵的引用不会被保存, 并且不能被释放。我知道我可以创建一个中间变量来进行引用,但我想保留嵌套函数调用,因为它简洁直观。我的整体设计有问题吗?如何克服这个问题?

你可以这样做,但它会创建中间函数:

Matrix* use_and_free(Matrix* input, Matrix* (*fct)(Matrix *)) {
  Matrix* ret = fct(input);
  DeleteMatrix(input);
  return ret;
}

Matrix* fun3(Matrix* input){
    return use_and_free(fun1(input), &fun2);
}

未显示如何使用输入参数。决定谁拥有分配的矩阵。这样行吗? (假设所有权转移给 fun2)

Matrix* fun2(Matrix* input){
    //some operations
    Matrix* mat = InitializeMatrix(r, c);
    //some operations
    DeleteMatrix(input);
    return mat;
}

一个选择是更改函数原型,以便 fun1()fun2() 接受第二个参数,即指向 Matrix 的指针。然后你可以改变函数体,如果这个参数是 NULL,那么分配一个新的 Matrix,否则使用 output Matrix。例如:

Matrix* fun1(Matrix* input, Matrix* output){
    //some operations
    Matrix* mat;
    if (output == NULL){
        mat = InitializeMatrix(input->rows, input->cols);
    } else {
        mat = output;
    }
    //some operations
    return mat;
}

这里我假设你原函数中未声明的rc指的是inputMatrix的行数和列数.如果你想让fun1()分配一个新的Matrix,可以这样调用:

Matrix* result = fun1(input, NULL);

如果你想使用预分配的 Matrix:

Matrix* mtrx = InitializeMatrix(3, 3);
mtrx = fun1(input, mtrx);

如果您想将 fun1()fun2() 链接在一起:

mtrx = fun2(fun1(input, mtrx), mtrx);

尽管让外部函数调用进行分配可能会更好;这样 mtrx 永远是一个中间结果,你只需要创建一个新的 Matrix 指针就可以得到一个新的结果。请注意,您仍然需要为 mtrx:

分配 space
result = fun2(fun1(input, mtrx), NULL);

您可以将更多功能链接在一起,但这可能会越过门槛而变得不当:

result = fun3(fun2(fun1(input, mtrx), mtrx), NULL);

另外,请注意您的 DeleteMatrix() 功能有问题。无需将字段清零,您需要 free(mat) 以及 free(mat->matrix):

int DeleteMatrix(Matrix* mat){
    free(mat->matrix);
    free(mat);
    return 0;
}