Перебор массива, хранящегося в куче - PullRequest
0 голосов
/ 16 апреля 2019

Пожалуйста, рассмотрите следующий код:

// 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] или «стековую копию»?

Ответы [ 4 ]

4 голосов
/ 16 апреля 2019

Скопированы ли вещи [i] в ​​стек и сохранены в my_thing?

Да, в качестве копии памяти, а не глубокой копии.

Ичто значит my_thing.a = 10;do - изменяет ли он исходные вещи [i] или «стековую копию»?

Изменяет только стековую копию.Однако будьте осторожны при работе с указателями, см. Пример здесь

2 голосов
/ 16 апреля 2019

Строка

    Thing my_thing = things[i];

скопирует всю структуру из объектов [i] в ​​локальное my_thing, которое находится в стеке.Объем скопированных данных будет равен размеру структуры, поэтому, если структура большая, то там может быть скопировано много данных.

Строка

    my_thing.a = 10;

влияет только налокальное my_thing, которое находится в стеке.Оригинальные вещи [я] никогда не модифицируется.Код также будет работать так же, если вы введете const в указатель ввода, например:

void f(const Thing * things, int size) {
    for (int i = 0; i < size; i++) {
        Thing my_thing = things[i];
        my_thing.a = 10;
    }
}
1 голос
/ 16 апреля 2019

my_thing и things[i] - два разных объекта в памяти.Строка

Thing my_thing = things[i];

создает новый объект my_thing и копирует в него содержимое things[i].Любое дальнейшее изменение на my_thing (например, my_thing.a = 10;) не влияет на things[i], независимо от того, размещено ли оно в стеке или в куче.

В большинстве реализаций "стек" и "куча" - это просто разные диапазоны адресов в одном и том же сегменте памяти - между ними нет реальной разницы, за исключением того, как ведется учет объектов в этих областях.Итак, не имеет значения, что things[i] находится в куче, в то время как my_things находится в стеке, если рассматривать механизм копирования одного в другой.

0 голосов
/ 16 апреля 2019

Сначала вы попробовали, работает ли этот код, потому что обычно я пишу Thing* my_thing = things + i, чтобы получить каждую вещь в массиве.

Вы даете функции указатель на массив Thing, а не массив Thing.Вот почему things - это адрес первой вещи.

Чтобы получить следующую, нужно добавить i к базовому указателю, чтобы добраться до нужного адреса.

Как следующая строкаработает зависит от типа my_thing.

Если это указатель, как я объявил, он фактически отредактирует содержимое массива в куче и создаст только копию адреса в my_thing.Однако строка должна быть (*my_thing).a = 10;, чтобы вы фактически указали значение в адресе, на который указывает указатель.

Если это Thing my_thing = *(things + i), то будет создана локальная копия значения и следующая строкаизменит эту копию вместо исходного массива.

Надеюсь, этот ответ поможет вам понять, что на самом деле происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...