Когда стоит использовать указатель для структурирования в определении структуры? - PullRequest
4 голосов
/ 13 апреля 2009

Извините, если вопрос не ясен; Мне было довольно сложно объяснить это одним предложением.

Скажем, у меня есть struct с членом, который является struct, например, следующее:

struct A {
    struct B b;
};

Допустим, я хочу, чтобы экземпляры этой структуры всегда выделялись в куче. Есть ли что-то, что можно получить, изменив это на это? (то есть, удерживая указатель до struct B)

struct A {
    struct B *b;
};

В последнем случае у меня будет пара функций, таких как make_A и free_A, которые будут заботиться о выделении и отмене выделения памяти, на которую указывает b;

Единственный пример, который я могу придумать, где вторая форма может быть предпочтительнее, это когда не все экземпляры struct A фактически используют b. В этом случае память может быть сохранена путем выделения дополнительной памяти только тем экземплярам, ​​которые в ней нуждаются.

Есть ли другие случаи, когда вторая форма предлагает что-то полезное?

Ответы [ 3 ]

7 голосов
/ 13 апреля 2009

Если в каждом A будет ровно один B, вы должны , а не использовать указатель на B.

Помимо того, что вам не нужно беспокоиться о дополнительном управлении памятью, на самом деле медленнее и менее эффективно выделять B.

Даже если вы хотите передать указатель на B на другой код, вы все равно можете передать этот адрес.

5 голосов
/ 13 апреля 2009

Когда экземпляр B может совместно использоваться несколькими экземплярами A, вы получите указатель на B. Это помогает избежать дублирования и поддерживать версии B более чем в одном месте. Согласно комментарию Джонатана, это связано с тем, что нужно знать, когда нужно освободить память, и ссылаться на ссылки на Б.

3 голосов
/ 13 апреля 2009

Я думаю, что вы ударили по голове своим последним заявлением. Если не у каждого A есть B, то вы можете сэкономить память, используя указатель (ноль для тех A s без B).

Это вряд ли будет действительно полезно, если только совокупный размер всех неиспользованных B s составляет значительную долю доступной кучи.

Но я бы изменил ваше утверждение на «когда не все экземпляры A будут иметь ровно одну копию B» по следующей причине (а это другой случай, о котором вы просите):

Где B - это узел в списке (который также содержит указатель на другой B или ноль), я бы сделал его указателем [хотя вы все равно можете встроить первый узел , если все A должны иметь хотя бы один B].

Другая возможность делится B с A с, если их природа это позволяет (например, A - это окно на экране B), хотя вам придется подсчитывать ссылки B s в этом случае, чтобы знать, когда, наконец, освободить их в ваших free_A() вызовах (и, конечно, возможность повторно использовать уже существующий B в ваших make_A() вызовах).

...