Указатель против элементов без указателя класса
Мои вопросы: предположим, что у нас есть два класса 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*
.