Динамическое выделение структуры внутри структуры - PullRequest
4 голосов
/ 26 марта 2012

Я динамически выделяю структуру, которая имеет другую структуру в качестве члена:

struct a {
   // other members
   struct b;
}

struct b в основном содержит указатель на другой struct b, поэтому представьте себе struct b как связанный список.

Если я динамически выделю struct a, то это также создаст новый struct b внутри него.Однако в чем разница между тем, чтобы struct a удерживал указатель на struct b и динамически размещал struct b в struct a?В чем разница в реализации?

Ответы [ 3 ]

10 голосов
/ 26 марта 2012

Во-первых, давайте создадим некоторые реальные определения, чтобы сделать этот бетон.

struct b {
    int x;
};

struct a_with_b {
    struct b b;
}

struct a_with_b_ptr {
    struct b *bp;
}

Когда вы инкапсулируете структуру, вам просто нужно выделить внешнюю структуру (и поскольку внутренняя структура не является указателем, вы используете . для ссылки на члены структуры innert):

struct a_with_b *a1 = malloc(sizeof(struct a_with_b));
a1->b.x = 3;

Но когда вы инкапсулируете указатель, вы должны выделять каждый независимо и использовать -> при обращении к элементам внутренней структуры:

struct a_with_b_ptr *a2 = malloc(sizeof(struct a_with_b_ptr));
a1->b = malloc(sizeof(struct b));
a1->b->x = 3;
8 голосов
/ 26 марта 2012

Если вы динамически выделяете (malloc) struct a как в

struct a *temp = (struct a *)malloc(sizeof(struct a));

вам malloc место для указателя на struct b (при условии, что это в struct a), но вы неt malloc пробел для struct b.Это означает, что позже вам придется выполнить

temp->b = (struct b *)malloc(sizeof(struct b));

, прежде чем пытаться использовать struct b.

Если вы не сохраните указатель на struct b, а скорее struct bнепосредственно тогда вы получите автоматическое распределение при определении struct a.

3 голосов
/ 26 марта 2012

Разница действительно эквивалентна любой другой ситуации, в которой вы сравниваете «автоматическое» и «динамическое» распределение. 1

С точки зрения руководства, когда вы должны использоватьчлен указателя, я бы сказал, что вам следует избегать этого, если нет веской причины не делать этого из-за накладных расходов программиста, связанных с ручным управлением памятью (и ошибками, к которым это неизбежно приводит).

Примерхорошая причина - если вам нужна ваша структура a для ссылки на существующую структуру b.


1.«автоматический» - это термин, используемый в стандарте C для такого распределения, потому что память очищается автоматически.
...