C 使用方法链接时释放指针的正确方法
我目前正在用c编写多个不同的矩阵乘法实现。因此,我编写了矩阵加减的实用函数,其结构如下:C 使用方法链接时释放指针的正确方法,c,memory-management,free,C,Memory Management,Free,我目前正在用c编写多个不同的矩阵乘法实现。因此,我编写了矩阵加减的实用函数,其结构如下: int** m_sub(int** a, int** b, int size) { int **result = get_matrix(size); // calculate addition of a & b return result; } 使用get_matrix(): 我知道我可以通过将每个返回的int**分配给一个变量,然后手动释放它来解决这个问题。然而,这将导致
int** m_sub(int** a, int** b, int size) {
int **result = get_matrix(size);
// calculate addition of a & b
return result;
}
使用get_matrix():
我知道我可以通过将每个返回的int**
分配给一个变量,然后手动释放它来解决这个问题。然而,这将导致大量临时分配的变量,从而(可以说)减少代码的可读性
现在我想知道在c中是否有一种“正确”的方法来实现这一点?或者我返回的是“代码> int *>代码>指针,这些矩阵已经是一个坏的设计选择?< p>问题是C没有自动析构函数调用的概念,如C++一样。好吧,作为程序员,你有责任释放任何分配的东西 当然,您可以想象这样一个库,它保存它所分配的任何内容的引用,并在您不再需要它时提供一种释放这些内容的方法。例如,您可以实现一个动态堆栈来存储每个新分配的内存块,并在以后使用该堆栈回收整个内存
只是我太懒了,无法编写它的实现。。。但是,如果你觉得你想这样做,但不能从一开始就实现它,请随意在评论中ping我。实际上,在C中手动释放每个指针是正确的方法,因为正如Serge所写的,C中没有自动析构函数调用。但是,你可以在不使用动态堆栈或垃圾堆的情况下,使其手动且漂亮收藏家式的解决方案,在我看来,这通常是一个巨大的过度杀伤力。所以不用再麻烦了
int*创建_矩阵(int大小)代码>
int*
,而不是int**
。它更方便,不需要您进行所有的二维分配,您只需分配一个大小为n*n
的数组即可。在内存中,这是相同的空间。但是,如果愿意,您可以坚持使用二维
void delete_矩阵(int*matrix)代码>
int*matmul\u递归(int*left,const int*right,int size)代码>
右侧
,因此常量为。我们将修改左侧
,因此没有常量。现在将left
和right
的乘法写入left
。没有额外分配意味着没有泄漏。函数应该返回left
,以方便链式调用
注意,您可以添加一个int*create\u matrix\u copy(const int*source,int size)代码>以克隆矩阵
还要注意的是,在操作之后,通常不需要操作的参数。您将对生成的累积矩阵感兴趣。请参见此示例(使用函数名):
如果适用,也可以使用const
,即不更改参数的值,以避免错误。也可以考虑使用<代码>无符号int >代码>大小。
通常情况下,您可能会在一个矩阵上执行许多操作,因此这将更常见(如3D变换):
在C
中,您没有C++
中所拥有的奢侈品,因此内存分配只留给您。如果您确实希望避免逐个取消分配矩阵,可以执行以下操作:
创建一个struct
,负责存储所创建矩阵的所有地址(我们称之为容器)
因此,您的函数还将获取指向该矩阵容器对象的指针。当调用get_矩阵时,新分配的矩阵的地址被添加到容器中
在计算结束时,您需要做的就是正确地释放容器
类似于以下内容(下面的伪代码):
destroy_container
在矩阵向量上循环并逐个释放它们
请不要认为注释get_matrix
中所述的有问题<代码>整数**m=malloc(大小*大小(整数))代码>应该是int**m=malloc(size*sizeof(int*)
因为您需要为指针分配空间,而不是为int
s分配空间。您不能反过来做吗?在循环中释放m[i]
指针,最后释放**m
?(@Inian的意思是free(m[i]);
在循环中,然后free(m);
)是的,我知道如何通过循环释放从get_matrix()
获得的矩阵。问题更多的是“即使我不将返回的int**
赋值给变量,但直接将其用作另一个函数的参数,我是否可以释放它们?”int**m=malloc(size*sizeof(int))
非常错误,它假定指针的大小是整数的大小。它应该是int**m=malloc(size*sizeof*m)
,即sizeof(int*)
,但没有重复类型,并且对所讨论的变量有一点“锁定”。我一直在考虑类似的事情。所以你会建议在计算中使用某种“全局”堆栈,并将所有临时变量推到上面,对吗?没错。它可以是编译单元中的静态成员,其中包含分配和解除分配的例程-注意,不要忘记显式初始化i
int** get_matrix(int size){
int** m = malloc(size*sizeof(int));
for (int i=0;i<size;i++){
m[i] = malloc(size*sizeof(int));
}
return m;
m_copy(c_11,m_add(matmul_recursive(n/2, a,e),matmul_recursive(n/2, b, g), n/2), n/2);
int* arg1 = create_matrix(n);
int* arg2 = create_matrix(n);
int* product1 = create_matrix(n);
int* product2 = create_matrix(n);
int* result = m_add(matmul_recursive(product1, arg1, n), matmul_recursive(product2, arg2, n), n);
delete_matrix(arg1);
delete_matrix(arg2);
delete_matrix(product2);
printf("%d", product1[0]);
printf("%d", result[0]); // result == product1
delete_matrix(product1);
int* result = create_matrix(n);
int* rotate = create_matrix(n);
int* translate = create_matrix(n);
int* scale = create_matrix(n);
matmul_recursive(matmul_recursive(matmul_recursive(result, rotate, n), translate, n), scale, n);
printf("%d", result[0]);
// Remember to delete all arguments.
int** get_matrix(int size, struct MatricesContainer* cnt){ //takes the container
int** m = malloc(size*sizeof(int));
for (int i=0;i<size;i++){
m[i] = malloc(size*sizeof(int));
}
vector_push_back(m, cnt); //push_the address in the container
return m;
}
int** m_sub(int** a, int** b, int size, struct MatricesContainer* cnt) {
int **result = get_matrix(size, cnt); //address of result is stored in cnt
// calculate addition of a & b
return result;
}
int heavy_calculation(...)
{
struct MatricesContainer* cnt
.....
m_copy(c_11,m_add(matmul_recursive(n/2, a,e, cnt),matmul_recursive(n/2, b, g,cnt), n/2), n/2,cnt);
...
destroy_container(cnt);
}