破坏从工厂方法初始化的参考成员

时间:2016-09-26 16:54:25

标签: c++ reference member factory-method

要初始化引用成员而不引用传递给包含类的构造函数的外部实体,可以使用工厂方法,如下所示:

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()会失败,还是会这样?

有更清洁的解决方案吗?

2 个答案:

答案 0 :(得分:4)

delete &a;的析构函数中的

B应该正确地完成工作以避免内存泄漏。

我最好推荐工厂功能,而应该返回std::unique_ptr<A>。或者您只是使用A的普通实例作为B的成员。

答案 1 :(得分:1)

更清洁的解决方案是避免将指针转换为引用。引用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