Каков предпочтительный способ размещения данных членов класса C ++? - PullRequest
3 голосов
/ 01 сентября 2010

Допустим, у меня есть класс, который выделяет некоторые произвольные данные члена. Я видел два распространенных способа (я знаю, что есть и другие):

class A
{
    public:
        A();
        ~A();

        //Accessors...
    private:
        B *mB;
}

A::A()
{
    mB = new B();
}

A::~A()
{
    delete B;
}

Versus ...

class A
{
    public:
        //Accessors...
    private:
        B mB;
}

Предположим, что сам A будет выделяться в куче кодом потребителя.

В общем случае, какой метод предпочтительнее? Я понимаю, что конкретные ситуации действительно поощряют так или иначе, но в отсутствие этих требований один из них предпочтителен? Каковы компромиссы?

Ответы [ 4 ]

9 голосов
/ 01 сентября 2010

Второй предпочтительный маршрут.Не используйте new / delete, если вам не нужна переменная, которая должна быть в куче или иметь срок жизни больше, чем ее контейнер.С типами значений C ++ проще управлять, и у них меньше ошибок, чтобы беспокоиться о IMHO

4 голосов
/ 01 сентября 2010

Это зависит.

В общем, если B большой и громоздкий, то легче передать указатель на B, чем сам B.Так что, если B часто будет отделен от A (например, если ваш B поменяется местами), то первый способ лучше.

Использование указателя также может уменьшить зависимости.Если вы все сделаете правильно, A.hh может обойтись без указания того, что B или делает (то есть A.h не нужно #include "B.hh"), так что вещи, которые зависят от A.hh, не обязательно будут зависеть от B.hh.

Цена использования указателей - это дополнительный уровень техники и опасности таких вещей, как потерянные объекты, двойное удаление и разыменование неинициализированных указателей, поэтому его не следует использовать, если он фактически не дает преимущества втвоя ситуация.Некоторые люди влюбляются в методы указателя и используют их повсюду;если они хотят стать программистами, они должны вырасти из этого.

0 голосов
/ 01 сентября 2010

Это зависит, в основном, от того, что вы ищете.

Ради простоты : не используйте указатель. Поэтому второй выбор.

Управлять проще (не нужно беспокоиться об управлении памятью, глубоком копировании, глубокой константности и т. Д.).

Однако иногда вам могут понадобиться динамически распределяемые атрибуты:

  • если вам нужен полиморфизм (в противном случае у вас есть усечение)
  • если вы хотите сократить свои зависимости (в заголовочном файле) -> см. PIMPL здесь

Однако даже в этом случае передайте ответственность умному менеджеру (умный указатель, выделенный класс pimpl и т. Д.) *

0 голосов
/ 01 сентября 2010

В общем, предпочитаю прямую композицию (второй выбор).В этом случае нет шансов утечки памяти, и объект полностью расположен в непрерывном блоке памяти, что обеспечивает лучшую локальность кэша.

Вы можете использовать первый вариант, если вы реализуете PIMPL или у вас естьнеобходимость использовать один из нескольких возможных типов классов (через наследование).В этом случае обязательно используйте умный указатель (например, boost::shared_ptr) для управления памятью.

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