Уничтожить ссылочный элемент, инициализированный из фабричного метода

Чтобы инициализировать ссылочный член без ссылки на внешнюю сущность, переданную в конструктор содержащего класса, можно использовать метод фабрики, например:

struct B
{
B() : a(new_a()) {}
// factory
a& new_a()
{
A* a = new A;
return *a;
}
A& a;
};

Однако, конечно B::a не будет уничтожен, когда BКонец жизни, потому что это ссылка. Но нет доступа к B::a вне B, Так что это утечка памяти. Чтобы это исправить можно позвонить A::~A() от B::~B()

B::~B() {a.~A();}

Но я читал, что вручную вызывать деструкторы было нет-нет, поэтому вызов A::~A() в деструкторе B::~B() падает или нет?

Есть ли более чистое решение?

1

Решение

delete &a; в Bдеструктор должен делать работу правильно, чтобы избежать утечки памяти.

Я бы лучше порекомендовал фабричную функцию, а должен возвращать std::unique_ptr<A> хоть. Или вы просто используете простой экземпляр A как BУчастник

4

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

Более чистым решением было бы избежать преобразования указателя в ссылку. Ссылка A& a; член данных подразумевает, что struct B не владеет объектом, который a Рекомендации. Тем не менее, в вашем случае это так, и это создает путаницу.

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

Например, std::unique_ptr<A> a; член данных здесь четко показывает намерение владения, и в качестве бонуса, a будет автоматически выпущен, когда B уничтожен Вам даже не нужно ничего писать на ~B() деструктор.

В результате ваш new a() Функция может быть написана так:


std::unique_ptr<A> new_a() { return {new A()}; }

На самом деле вам не нужно писать new_a(), Стандартная библиотека C ++ уже определяет для вас такую ​​функцию: std::make_unique,

1

По вопросам рекламы [email protected]