首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >浅拷贝混淆

浅拷贝混淆
EN

Stack Overflow用户
提问于 2016-10-25 11:34:17
回答 2查看 4.2K关注 0票数 0

编辑:修正了注释中提到的bug,问题仍然存在,所以这个问题并不是真的重复--只是我的C编程技巧在这一点上不是很好,下面给出的解决方案回答了这个问题,并且没有解决局部变量错误。

警告:C语言很新

我知道,当我们将一个结构分配给另一个结构时,就会执行一个浅拷贝。不过,我不明白为何会出现这样的情况:

假设下面我尝试初始化一个结构,通过使用赋值操作符将它称为Type2结构,Type1成员,那么应该已经执行了一个浅拷贝。这意味着复制Type2成员的地址:

代码语言:javascript
复制
typedef struct {
    uint8_t someVal;
} Type1

typedef struct {
    Type1 grid[3][3];
} Type2

//Constructor for Type2 "objects"
Type2 Type2_Constructor(void) {
    Type1 empty = {.value = o}
    Type2 newType2;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++) {
            //Shallow copy empty struct
            newType2.grid[i][j] = empty;
        }
    return newType2;
}

int main (void) {    
    Type2 type2Object = Type2_Constructor();   
    for (int i = 0; i < 3; i ++) 
        for (int j = 0; j < 3; j++){
            printf("%u",type2OBject.grid[i][j].value);
            printf("\n\r%p\n\r",&(type2Object.grid[i][j].value));
            printf("\n\r");
        }   
    return 0;
}

我希望看到:

代码语言:javascript
复制
0
0xMemoryLocation

0
0xMemoryLocation

0
0xMemoryLocation

.
.
.

实际上,我看到的是这样的情况,地址增加了2个字节:

代码语言:javascript
复制
0
0x7fff57eaca18

0
0x7fff57eaca1a

0
0x7fff57eaca1c

0
0x7fff57eaca1e

0
0x7fff57eaca20

.
.
.

既然浅拷贝应该直接复制地址,为什么&(type2Object.gridi.value)不同?

谢谢你的帮助!

EN

回答 2

Stack Overflow用户

发布于 2016-10-25 11:57:22

你似乎误解了什么是浅薄/深拷贝。一个浅拷贝将复制每个成员(或者按位复制(如果愿意)。深度复制还会复制结构的自有资源。

让我们从一个简单的例子开始:

代码语言:javascript
复制
struct X {
   int val;
};

X x1 = {24};
X x2 = {42};

x1 = x2;

是的,内建赋值运算符=确实执行一个浅拷贝.这意味着上述内容相当于:

代码语言:javascript
复制
x1.val = x2.val;

在这种情况下,由于X没有,它没有外部资源,所以它也被认为是一个深拷贝,因为x2拥有的每一个东西都被复制到x1。这是X不拥有任何外部资源的结果。

X拥有外部资源/例如:

代码语言:javascript
复制
struct X {
   int *my_very_own_external_value;
};

X x1, x2;
x1.my_very_own_external_value = malloc(sizeof(int));
*x1.my_very_own_external_value = 24;

x2.my_very_own_external_value = malloc(sizeof(int));
*x2.my_very_own_external_value = 42;

一个浅显的副本是这样的:

代码语言:javascript
复制
x1 = x2;

这相当于:

代码语言:javascript
复制
x1.my_very_own_external_value  = x2.my_very_own_external_value;

如果您理解指针意味着x1丢失了它分配的内存的地址(谁持有24),现在x1x2都有指向为x2分配的内存的指针,即存储42的内存;

如果你想要一份深刻的副本,你需要写:

代码语言:javascript
复制
free(x1.my_very_own_external_value);
x1.my_very_own_external_value  = malloc(sizeof(int));
*x1.my_very_own_external_value  = *x2.my_very_own_external_value;

现在,您已经复制了x2外部拥有的内存(外部资源)。

免责声明:我可能是用C++风格写的

票数 3
EN

Stack Overflow用户

发布于 2016-10-25 12:01:37

您的代码有一个bug:

代码语言:javascript
复制
//Constructor for Type2 "objects"
Type2 * Type2_Constructor(void) {
    Type1 empty = ...;
    Type2 newType2;
    ... do something ...
    Type2 * newType2Ptr = &newType2;
    return newType2Ptr;
}

newType2是一个局部变量--一个在堆栈上定义的结构。然后将其地址返回给调用函数。一旦退出Type2_Constructor函数,它的堆栈就不再掌握在您手中了。

当您从这个区域打印值时,您会得到各种各样的东西(您可能希望得到一个核心转储,但遗憾的是,情况并不总是这样)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40238872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档