请考虑以下代码:
// Thing is a typedef struct
void f(Thing* things, int size) {
for (int i = 0; i < size; i++) {
Thing my_thing = things[i];
my_thing.a = 10;
}
}
由things
指向的数组分配在堆上的某个位置。
然而-my_thing
是一个“堆栈变量”-在堆栈上分配。
那么幕后发生了什么? things[i]
是否已复制到堆栈并存储在my_thing
中? my_thing.a = 10;
会做什么-它会修改原始的things[i]
还是会修改“堆栈副本”?
答案 0 :(得分:4)
事物[i]是否已复制到堆栈中并存储在my_thing中?
是的,作为内存副本,不是深层副本。
my_thing.a = 10是什么?会-会修改原始内容[i]还是会修改“堆栈副本”?
它仅修改堆栈副本。但是,在处理指针时要小心,请参见示例here
答案 1 :(得分:2)
行
Thing my_thing = things[i];
会将整个结构从事物[i]复制到堆栈上的本地my_thing。复制的数据量将是该结构的大小,因此,如果该结构较大,则可能会有很多数据复制到该结构。
行
my_thing.a = 10;
仅影响堆栈上的本地my_thing。原始事物[i]从未修改。如果将const
放在输入指针上,代码也将以相同的方式工作,如下所示:
void f(const Thing * things, int size) {
for (int i = 0; i < size; i++) {
Thing my_thing = things[i];
my_thing.a = 10;
}
}
答案 2 :(得分:1)
my_thing
和things[i]
是内存中两个不同的对象。线
Thing my_thing = things[i];
创建一个新对象my_thing
并将things[i]
的内容复制到其中。对my_thing
的任何进一步更改(例如my_thing.a = 10;
)对things[i]
都没有影响,无论是在堆栈还是在堆上分配。
在大多数实现中,“堆栈”和“堆”只是同一内存段中的不同地址范围-它们之间没有真正的区别,只是对那些区域内的对象进行簿记的方式不同。 IOW,将things[i]
放在堆上而将my_things
放在堆栈上,就复制一个到另一个的机制没关系。
答案 3 :(得分:0)
首先,您是否尝试过此代码是否还能正常工作,因为通常我会写Thing* my_thing = things + i
来获取数组中的每个Thing。
为函数提供指向Thing而不是Thing数组的指针。这就是为什么things
是第一件事的地址。
要获取下一个,必须将i添加到基本指针中,以获取所需的地址。
下一行的工作方式取决于my_thing是什么类型。
如果它是我声明的指针,它将实际上编辑堆上数组的内容,并且仅在my_thing中创建地址的副本。但是,该行应为(*my_thing).a = 10;
,以便您将值实际设置为指针所指向的地址。
如果它是Thing my_thing = *(things + i)
,则将创建该值的本地副本,下一行将更改该副本,而不是原始数组。
我希望这个答案可以帮助您了解实际情况。