2016-09-26 87 views
1

要初始化的基准构件,而不传递给含类的构造的外部实体的引用,一个工厂的方法可用于,例如:自毁基准部件初始化

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

然而当B的生命期结束时,B::a当然不会被销毁,因为它是一个参考。但B之外没有访问B::a。所以这是一个内存泄漏。为了解决这个问题一个可以打电话从B::~B()

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

A::~A()但我已阅读手动调用析构函数是一个没有没有,所以把以A::~A()来电的B::~B()析构函数放平,或不是吗?

有更清洁的解决方案吗?

+5

我认为你需要重新考虑你的设计。例如,*为什么*你必须有一个参考?难道你没有一个实际的实例(这是我推荐的)?还是一个指针(或者说是一个智能指针)? –

+0

'return * a;'引用指针。 '''a''''''''''''''''''''''''''''''''',''''A''的一个副本被卷起,但''''''A'被泄漏。 – user4581301

+0

@ user4581301没有。 'new_a'返回一个引用(假设返回类型应该是'A&'不''a&')并且直接绑定到'B :: a'。没有副本。 –

回答

4

delete &a;B的析构函数应该正确地做这项工作以避免内存泄漏。

我最好推荐工厂函数,而应该返回std::unique_ptr<A>。或者,您只需使用A的简单实例作为B的成员。

1

更清洁的解决方案是避免将指针转换为引用。数据成员参考A& a;意味着struct B不拥有a引用的对象。但是,就你的情况而言,它会造成混淆。

您应该更喜欢非拥有关系的引用(和原始指针),以及拥有关系的智能指针或值对象。

例如,std::unique_ptr<A> a;此处的数据成员将清楚地显示所有权意图,并且作为奖励,将在B销毁时自动发布。你甚至不需要在~B()析构函数中写任何东西。

其结果是,你new a()功能可以这样写:

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

其实你不需要写new_a()。 C++标准库已经为你定义了一个这样的函数:std::make_unique

+1

'unique_ptr'有一个显式的构造函数,所以你需要做'return std :: unique_ptr {new A};'(或'return std :: make_unique ();',如你所说)。 –