如何复制C中包含指针的结构?
我有一个向量类型,定义如下:如何复制C中包含指针的结构?,c,C,我有一个向量类型,定义如下: typedef struct vector { void **items; unsigned int capacity; unsigned int size; } vector_st; typedef vector_st *vector_t; vector_t vector_init(unsigned int capacity) { vector_t v = (vector_t)calloc(1, sizeof(vector_st
typedef struct vector {
void **items;
unsigned int capacity;
unsigned int size;
} vector_st;
typedef vector_st *vector_t;
vector_t vector_init(unsigned int capacity)
{
vector_t v = (vector_t)calloc(1, sizeof(vector_st));
v->capacity = capacity;
v->size = 0;
v->items = malloc(sizeof(void *) * v->capacity);
return v;
}
void vector_free(vector_t v)
{
if (v) {
free(v->items);
v->capacity = 0;
v->size = 0;
free(v);
v = NULL;
}
}
我按如下方式分配和释放它:
typedef struct vector {
void **items;
unsigned int capacity;
unsigned int size;
} vector_st;
typedef vector_st *vector_t;
vector_t vector_init(unsigned int capacity)
{
vector_t v = (vector_t)calloc(1, sizeof(vector_st));
v->capacity = capacity;
v->size = 0;
v->items = malloc(sizeof(void *) * v->capacity);
return v;
}
void vector_free(vector_t v)
{
if (v) {
free(v->items);
v->capacity = 0;
v->size = 0;
free(v);
v = NULL;
}
}
现在,重点是我想把一个向量复制到另一个向量,这意味着包括它的所有内容。因此,我尝试定义一个如下函数:
void vector_copy(vector_t to, vector_t from)
{
memcpy(to, from, sizeof(vector_st));
}
vector_t vec = vector_init(3);
vector_add(vec, 1);
vector_add(vec, 2);
vector_add(vec, 3);
unsigned int i;
for (i = 0; i < vec->size; i++) {
printf("%d\n", (int)vector_get(vec, i));
}
vector_t copied = vector_init(3);
vector_copy(copied, vec);
vector_free(vec);
for (i = 0; i < copied->size; i++) {
printf("%d\n", (int)vector_get(copied, i));
}
void vector_copy(vector_t to, vector_t from, size_t element_size) {
// NOTE: robust code would check for memory allocation failures. This code does not.
void **temp_items;
to->capacity = from->capacity;
to->size = from->size;
// evaluates to NULL if allocation fails:
temp_items = realloc(to->items, from->capacity * sizeof(*to->items));
to->items = temp_items;
for (int i = 0; i < from->size; i++) {
to->items[i] = malloc(element_size); // evaluates to NULL if allocation fails
memcpy(to->items[i], from->items[i], element_size);
}
}
但是,这似乎并不完全正确,因为当我做这样的事情时:
void vector_copy(vector_t to, vector_t from)
{
memcpy(to, from, sizeof(vector_st));
}
vector_t vec = vector_init(3);
vector_add(vec, 1);
vector_add(vec, 2);
vector_add(vec, 3);
unsigned int i;
for (i = 0; i < vec->size; i++) {
printf("%d\n", (int)vector_get(vec, i));
}
vector_t copied = vector_init(3);
vector_copy(copied, vec);
vector_free(vec);
for (i = 0; i < copied->size; i++) {
printf("%d\n", (int)vector_get(copied, i));
}
void vector_copy(vector_t to, vector_t from, size_t element_size) {
// NOTE: robust code would check for memory allocation failures. This code does not.
void **temp_items;
to->capacity = from->capacity;
to->size = from->size;
// evaluates to NULL if allocation fails:
temp_items = realloc(to->items, from->capacity * sizeof(*to->items));
to->items = temp_items;
for (int i = 0; i < from->size; i++) {
to->items[i] = malloc(element_size); // evaluates to NULL if allocation fails
memcpy(to->items[i], from->items[i], element_size);
}
}
所以,基本上我认为它只是复制了内存地址,而不是实际的内容
是的,因为在这条线上
memcpy(to, from, sizeof(vector_st));
您只需将分配给的内存丢弃到,这样复制的所持有的内存就会泄漏;在vector\u free(vec)
复制后
现在持有一个对已释放内存的悬空引用
要将vector的内容复制到另一个,那么,复制它:
memcpy(to->items, from->items, sizeof(void *) * from->size);
(或效率较低)
int i;
for(i = 0; i < from->size; ++i) to->items[i] = from->items[i];
所以,基本上我认为它只是复制了内存地址,而不是实际的内容
是的,因为在这条线上
memcpy(to, from, sizeof(vector_st));
您只需将分配给的任何内存丢弃到,这样复制的所持有的内存就会泄漏;在无向量(vec)
复制的之后,现在会持有对已释放内存的悬空引用
要将vector的内容复制到另一个,那么,复制它:
memcpy(to->items, from->items, sizeof(void *) * from->size);
(或效率较低)
int i;
for(i = 0; i < from->size; ++i) to->items[i] = from->items[i];
这是错误的,因为向量
拥有其项
对象。因此,您需要在向量_copy
中执行四项操作:
1) 释放目标向量中现有的项
对象,使其不会泄漏。
2) 复制容量
和大小
3) 为目标向量分配全新的项目。
4) 将源项目
复制到新分配的目标项目
如果将代码> VCordRoSimult/COD>作为初始化函数,跳过第1步。但是在这种情况下,我强烈建议将名称改为
vector\u init
,这样就可以清楚地看到它创建了一个新的向量
这是错误的,因为向量
拥有其项
对象。因此,您需要在vector\u copy
中执行四项操作:
1) 释放目标向量中现有的项
对象,使其不会泄漏。
2) 复制容量
和大小
3) 为目标向量分配全新的项目。
4) 将源项目
复制到新分配的目标项目
如果将代码> VCordRoSimult/COD>作为初始化函数,跳过第1步。但是在这种情况下,我强烈建议将名称改为
vector\u init
,这样就可以清楚地看到它创建了一个新的向量
现在,重点是我想把一个向量复制到另一个向量,这意味着包括它的所有内容
您似乎想要执行的操作称为“深度复制”。这意味着不仅要递归地复制数据,还要复制指向数据的任何附加数据。您已经正确地判断出结构本身的memcpy()
不会这样做;向量元素由结构中的指针指向,但它们本身位于其他位置,因此不会被复制
更糟糕的是,在复制指向的数据时存在一个基本问题:复制函数不知道指向的元素有多大。没有这些知识,就不可能复制它们。此外,如果元素本身包含指针,那么要执行真正的深度复制,您需要关于这些成员以及它们指向的对象有多大的信息。等等
因此,基本上不可能(用任何语言)编写通用的深度副本。执行深度复制需要在每个级别上提供有关您正在复制的内容的信息。然而,为了给您一点味道,如果您可以依赖于向量元素具有在调用时已知的一致大小,那么您可以复制更深一层。可能看起来像这样:
void vector_copy(vector_t to, vector_t from)
{
memcpy(to, from, sizeof(vector_st));
}
vector_t vec = vector_init(3);
vector_add(vec, 1);
vector_add(vec, 2);
vector_add(vec, 3);
unsigned int i;
for (i = 0; i < vec->size; i++) {
printf("%d\n", (int)vector_get(vec, i));
}
vector_t copied = vector_init(3);
vector_copy(copied, vec);
vector_free(vec);
for (i = 0; i < copied->size; i++) {
printf("%d\n", (int)vector_get(copied, i));
}
void vector_copy(vector_t to, vector_t from, size_t element_size) {
// NOTE: robust code would check for memory allocation failures. This code does not.
void **temp_items;
to->capacity = from->capacity;
to->size = from->size;
// evaluates to NULL if allocation fails:
temp_items = realloc(to->items, from->capacity * sizeof(*to->items));
to->items = temp_items;
for (int i = 0; i < from->size; i++) {
to->items[i] = malloc(element_size); // evaluates to NULL if allocation fails
memcpy(to->items[i], from->items[i], element_size);
}
}
void vector\u copy(vector\u t to,vector\u t from,size\u t element\u size){
//注意:健壮代码将检查内存分配失败。此代码不会。
作废**临时项目;
到->容量=从->容量;
到->大小=从->大小;
//如果分配失败,则计算为NULL:
temp_items=realloc(to->items,from->capacity*sizeof(*to->items));
至->项目=临时项目;
对于(int i=0;isize;i++){
to->items[i]=malloc(元素大小);//如果分配失败,则计算结果为NULL
memcpy(to->items[i],from->items[i],元素大小);
}
}
您可以通过使元素成为向量结构的成员来避免传递元素大小
注意,这假设向量到已经初始化,并且不需要释放指向当前在其中的单个项(如果有)的指针(即向量不拥有这些项,因此不负责管理它们的内存)
现在,重点是我想把一个向量复制到另一个向量,这意味着包括它的所有内容
您似乎想要执行的操作称为“深度复制”。这意味着不仅要递归地复制数据,还要复制指向数据的任何附加数据。您已经正确地判断出结构本身的memcpy()
不会这样做;向量元素由结构中的指针指向,但它们本身位于其他位置,因此不会被复制
更糟糕的是,在复制指向的数据时存在一个基本问题:复制函数不知道指向的元素有多大。没有这些知识,就不可能复制它们。此外,如果元素本身包含指针,那么要执行真正的深度复制,您需要关于这些成员以及它们指向的对象有多大的信息。等等
那么基本上是