有一些问题就像这个问题,但它们与我提出的具体问题并不相似.
我的问题是如何使用指针作为成员制作结构的深层副本,以及如何使用指针作为成员制作结构的SHALLOW副本.然后,仅供参考,如何使用指针成员制作结构的深层副本以及如何使用指针成员制作结构的浅表副本(不确定最后一个是否有意义).
假设我们有这个:
typedef struct Student
{
char* first_name;
char* last_name;
int grade;
long id;
} Student;
Run Code Online (Sandbox Code Playgroud)
这是我创建一个学生的通用函数(标题很难格式化):
Student* create_student(const char* first_name, const char* last_name, int grade,long id)
{
Student *newStudentp = (malloc(sizeof(Student)));
newStudentp -> last_name = (malloc((strlen(last_name) + 1) * sizeof(char)));
newStudentp -> first_name = (malloc((strlen(first_name) + 1) * sizeof(char)));
strncpy(newStudentp -> first_name, first_name, strlen(first_name) + 1);
strncpy(newStudentp -> last_name, last_name, strlen(last_name) + 1);
newStudentp -> grade = grade;
newStudentp -> id = id;
return newStudentp;
}
Run Code Online (Sandbox Code Playgroud)
我试图制作一份深刻而浅薄的副本;
int main()
{
Student *s1 = create_Student("Bo","Diddly", 100, 221);
Student *s2 = create_Student("Leeroy","Jenkins",50,1337);
memcpy(&s2,&s1,sizeof(Student)); //shallow copy of s1 INTO s2?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于带有指针成员的结构的深层副本,我知道我们必须使用我们自己的复制函数来做一些对指针敏感的事情.那个明智的事情是......我不确定......所以这是我对这个DEEP副本的尝试.
void copy_Student(Student *s1, Student *s2)
{
s2 -> grade = s1 -> grade;
s2 -> id = s1 -> id;
s2 -> first_name = s1 -> *first_name;
s2 -> last_name = s1 -> *last_name;
}
Run Code Online (Sandbox Code Playgroud)
我的问题的另一部分(没有指针作为成员的结构)可能只是口头解释.
阅读后获得有用的评论:
浅拷贝:memcpy(s2,s1,sizeof(学生));
深拷贝:
void free_student(Student* stu)
{
free(stu -> first_name);
free(stu -> last_name);
}
void copy_Student(Student *s1, Student *s2)
{
s2 -> grade = s1 -> grade;
s2 -> id = s1 -> id;
s2 -> first_name = strdup(s1 -> first_name);
s2 -> last_name = strdup(s1 -> last_name);
}
Run Code Online (Sandbox Code Playgroud)
浅拷贝和深拷贝的区别可以用一句话来解释:浅拷贝复制的是指针;浅拷贝复制的是指针。深拷贝复制它们所指向的内容。
从问题的最后一部分开始:如果没有指针,则浅拷贝和深拷贝之间没有区别。
您尝试进行浅复制在技术上是正确的。但这在逻辑上是错误的。您的函数( sdelete_student()
的函数)无法处理浅拷贝。它不知道还有多少其他学生副本,并且您需要延迟直到删除最后一个副本。free
malloc
free()
深拷贝有一个非常相关的问题。这在技术上是不正确的。奇怪的是,您的create_student()
函数表明您确实知道如何将 a 复制到另一个函数 - 该函数具有和char*
的深层副本。你也应该这样做。first_name
last_name
copy_Student
您列出的作为浅层副本的代码不是; 它实际上会粉碎堆栈并可能导致程序崩溃.
Student *s1 = create_Student("Bo","Diddly", 100, 221);
Student *s2 = create_Student("Leeroy","Jenkins",50,1337);
memcpy(&s2,&s1,sizeof(Student)); //shallow copy of s1 INTO s2?
Run Code Online (Sandbox Code Playgroud)
如果你的尺寸合适,那将是相同的s2 = s1;
.但是由于你的大小错误,它复制太多并且会在s2之后覆盖内存中的内容.要做一个真正的浅层副本,请不要理解&
:
memcpy(s2,s1,sizeof(Student)); //shallow copy of s1 INTO s2
Run Code Online (Sandbox Code Playgroud)
您拥有深层拷贝的代码同样是错误的,但您处于正确的轨道上.深层复制背后的基本思想是你必须复制每个字段; 对于非指针类型,这与浅拷贝相同,但对于指针,你必须做更聪明的事情.但是,您发布的代码并没有这样做.试试这个.
void copy_Student(Student *s1, Student *s2)
{
s2 -> grade = s1 -> grade;
s2 -> id = s2 -> id;
s2 -> first_name = strdup(s1 -> first_name);
s2 -> last_name = strdup(s1 -> last_name);
}
Run Code Online (Sandbox Code Playgroud)
请注意,为了避免内存泄漏,您还需要s2
在分配新副本之前释放旧名称,创建一个free_Student
可以释放这些名称的函数,并确保create_Student
首先复制名称(或者包括"should免费"标志,所以你不必复制文字字符串).
现在,对于没有指针(或其他引用类型)的结构,深拷贝和浅拷贝之间没有区别,因为数据结构本身很浅.