Указатель против элементов без указателя класса

Мои вопросы: предположим, что у нас есть два класса A и B. Я хочу иметь объект B в классе A.

Должен ли я использовать

class A
{
  public:
          A();
          ~A();
          B* b;
};

или

class A
{
      public:
              A();
              ~A();
              B b;
};

Насколько я знаю, в первом сценарии я могу инициализировать объект *b с помощью оператора new, а для второго сценария я могу инициализировать b, используя список инициализации, если я не хочу используйте конструктор по умолчанию class B. Что удобнее использовать?

Ответ 1

Это зависит.

Даже если вы используете указатель, вы можете инициализировать член в списке инициализации, но это не ваша самая большая проблема.

Есть преимущества и недостатки обоих:

Использование указателя:

Плюсы:

  • класс будет меньше в памяти

  • вам нужно только объявление вперед для другого класса - не нужно включать другой заголовок в свой заголовок

  • может использовать производные объекты из B в качестве членов

Минусы:

  • Управление памятью - это довольно большой. Вы хотите, чтобы память управлялась классом (переопределить деструктор, оператор присваивания и конструктор копирования)?

Использование объекта:

Плюсы:

  • Не нужно беспокоиться об управлении памятью.

Минусы:

  • может использовать только объекты базового класса. Что делать, если вы хотите получить от B?

  • больше памяти для каждого экземпляра

  • конструктор B будет вызываться при построении A

  • вам нужно полное определение B внутри заголовка

Я отредактирую свой ответ, если буду думать больше.

Ответ 2

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

В общем, вы должны избегать динамически распределенной памяти как можно больше.

Ответ 3

Второй вариант удобнее, потому что вам не нужно самостоятельно управлять памятью. Нет new, no delete.

Если вы идете с первым, то вам, вероятно, придется также реализовать правило из трех (в С++ 03):

Или, правило 5 (в С++ 11):

Основная идея этого правила заключается в следующем:

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

Ответ 4

Используйте второе, старайтесь не использовать new как можно больше в С++, если вы не используете RAII.

Ответ 5

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

Вторая также более удобна практически для всех целей. Используйте только указатель, когда вам нужно, и даже тогда обработка ресурсов более удобна с помощью умного указателя, а не B*.