2016-04-25 55 views
1

我测试浅拷贝的结构与此代码:为什么结构浅拷贝不起作用?

#include "stdio.h" 
#include "conio.h" 

int main() { 

    struct str { 
     char * name; 
     int value; 
    }; 

    struct str str_1 = {"go", 255}; 
    struct str str_2; 

    str_2 = str_1; 

    str_1.name = "back"; 

    printf("%s\n",str_1.name); 
    printf("%s\n",str_2.name); 

    printf("\n"); 
    system("pause"); 
    return 0; 
} 

我期待的结果应该是:

back 
back 

但它是:

back 
go 

编辑:我预计,因为浅拷贝,str_1.namestr_2.name应该始终指向相同的pla CE。

编辑:并与动态分配的,我得到了我的预期:

#include <stdio.h> 
#include <conio.h> 
#include <string.h> 

int main() { 

    struct str { 
     char * name; 
     int value; 
    }; 

    struct str str_1; 
    struct str str_2; 

    str_1.name = (char*) malloc(5); 
    strcpy(str_1.name,"go"); 

    str_2 = str_1; 

    strcpy(str_1.name,"back"); 

    printf("%s\n",str_1.name); 
    printf("%s\n",str_2.name); 

    printf("\n"); 
    system("pause"); 
    return 0; 
} 

结果是:

back 
back 

什么是我误会吗?

+3

我不知道。你为什么期望你的预期?这不是什么“浅”的意思... –

+1

恕我直言,这个问题没有错。 “显而易见度”的程度不应该吸引downvotes。广义相对论对一些民间人士来说显而易见 – Bathsheba

+2

@Bathsheba:没错,但描述期望的缺乏吸引了低估。很难解释为什么这个世界不符合隐藏的期望。 –

回答

2

拿一张纸,慢慢地画出你认为正在发生的每一步,这应该变得清晰。

让我们画struct str像这样:

--------------------- 
| const char * name | 
--------------------- 
| int value   | 
--------------------- 

而且,我们表示在地址0xabcdef10为这样的字符串:

--0xabcdef10--------------------- 
| "string\0"     | 
--------------------------------- 

所以,当我们初始化str_1,我们需要一些内存位置将举行“去”,让我们打电话0xaaaaaa00

--0xaaaaaa00--------------------- 
| "go\0"      | 
--------------------------------- 

然后我们初始化str_1用一个指针:

struct str str_1 = {"go", 255}; 

--str_1--------------------------- 
| const char * name = 0xaaaaaa00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

现在我们采取的str_1浅拷贝,并将其命名为str_2

--str_2--------------------------- 
| const char * name = 0xaaaaaa00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

接下来我们执行str_1.name = "back";。和以前一样,我们首先要创建新的字符串。让我们把这点0xbbbbbb00

--0xbbbbbb00--------------------- 
| "back\0"      | 
--------------------------------- 

然后我们将其分配给str_1.name,所以str_1现在看起来像:

--str_1--------------------------- 
| const char * name = 0xbbbbbb00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

请注意,我们没有改变str_2

所以,当我们在看我们的最后的“记忆”中,我们看到:

--0xaaaaaa00--------------------- 
| "go\0"      | 
--------------------------------- 
    .... 

--0xbbbbbb00--------------------- 
| "back\0"      | 
--------------------------------- 
    .... 
--str_1--------------------------- 
| const char * name = 0xbbbbbb00 | 
---------------------------------- 
| int value = 255    | 
--str_2--------------------------- 
| const char * name = 0xaaaaaa00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

在新的字符串,所以str_1点,str_2点,老的字符串。

如果你描述为动态的,你永远不会更新结构中的指针,你可以通过相同的练习来找出在这种情况下发生的内存情况。

2

str_2 = str_1;确实采取浅拷贝。

但这并不意味着,任何后续改动什么name指向str_1会自动反映在str_2

(真的,您应该使用const char*作为字符串类型,因为您正在分配只读字符串文字)。

+0

我已经用动态分配案例编辑了这个问题,你能否在我的答案中更多地展示我? – Nik

1

str_2 = str_1;生成结构本身的硬拷贝。例如,value成员对于每个结构都是唯一的。

但是你得到了任何指针成员的软拷贝,因为拷贝不会影响任何指针的指向数据。意思是在复制之后,str_1str_2的指针name指向文字"go"

然后str_1.name = "back";只在str_1.name指向的地方变化。它不会改变str_2.name指向哪里。

当您使用malloc和strcpy时,您更改指向的数据并获取所有内容的完整硬拷贝。