Как написать код без ошибок, когда указатель связан?

Например

struct A
{
void foo() {};
};

struct B
{
B() {}

void setA(A* a) { mA = a; }
foo()           { mA->foo(); }

A *mA;
};

Есть A связанный (просто адрес) внутри B, А также B::mA не должен быть null, Я обычно забываю setA и ошибки введены. Какая хорошая практика, чтобы избежать этого? А как насчет setA как следующий?

void B::setA(A& a) { mA = &a; }

0

Решение

Первое, и самое главное, никогда не оставлять указатель
неинициализированный. Как минимум, установите его на nullptr (или же NULL в
pre-C ++ 11) в конструкторе, так что вы можете хотя бы проверить его на валидность
потом.

Помимо этого, многое зависит от того, на что оно должно указывать:

  • Если срок службы того, на что он указывает, гарантированно простирается за пределы
    время жизни вашего объекта (в обоих направлениях: он существует до вашего
    объект создан, и будет продолжать существовать после того, как ваш объект
    ), передайте его как ссылку на конструктор и возьмите
    адрес ссылки для инициализации указателя.

  • Если срок действия того, на что он указывает, может начаться только после
    объект построен, то вы должны установить указатель на нуль в
    конструктор, назначьте ему в setA и убедитесь, что это
    не нуль каждый раз, когда вы хотите его использовать.

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

  • Если время жизни вашего объекта должно влиять на время жизни
    указал на объект, то вы должны посмотреть на использование std::shared_ptr,
    Я обнаружил, что такие случаи очень редки в реальном коде, но они случаются.
    (Обратите внимание, что если вы используете std::shared_ptr, ты должен быть очень, очень
    осторожный. Вы можете построить только один std::shared_ptr из любого данного
    необработанный указатель без проблем. В нашей собственной кодовой базе мы
    запрещенный std::shared_ptrи использовать нашу собственную инвазивную ссылку
    указатель, чтобы избежать таких проблем. std::shared_ptr был
    тщательно разработан, чтобы максимизировать риск висящих указателей и
    несколько удалений одного и того же объекта.)

3

Другие решения

Лучший способ — избегать указателей. Если вам нужно использовать указатели, рассмотрите возможность использования умных указателей, таких как std::unique_ptr или же std::shared_ptr. И всегда, всегда инициализируйте указатели, либо равные нулю (если вы не используете умные указатели), либо тому, что вы выделили. И всегда всегда всегда проверьте на ноль, прежде чем использовать их.

6

Используйте ссылку в качестве первого выбора, если объект всегда инициализируется раньше B объект:

struct B
{
B(A& a) : mA(a) {}
foo() { mA.foo(); }
A& mA;
};

A a;
B b(a);
1

«Я обычно забываю setA, и появляются ошибки».

Поэтому заставьте себя установить его конструкторами:

struct B
{
public:
B(A *a) : ma(a) {}

private:
A *mA;
};

И разреши foo Проверь это:

foo()
{
if (mA)
mA->foo();
else
// handle it, throw exception, ignore, ...!
}
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector