2015-06-12 46 views
4

考虑下面的代码:为什么std :: shared_ptr的别名构造函数不初始化std :: enabled_shared_from_this?

struct Foo : std::enable_shared_from_this<Foo> 
{ 

}; 

struct Bar 
{ 
    Foo foo; 
}; 

int main() 
{ 
    std::shared_ptr<Bar> bar_p(new Bar); 

    //make shared_ptr to member with aliasing constructor 
    std::shared_ptr<Foo> foo_p(bar_p, &bar_p->foo); 
    assert(bar_p->foo.shared_from_this()); //fail! throws bad_weak_ptr 
} 

不幸的是,预期它不工作(至少在GCC 4.8.2)。我研究了代码,似乎别名构造函数根本不会调用__enable_shared_from_this_helper(),这对于shared_from_this()的正常工作是必需的。

有没有人知道为什么它是这样设计的?将shared_ptr从shared_from_this返回给成员有什么问题吗?

回答

6

[util.smartptr.shared.const]

template<class Y> shared_ptr(const shared_ptr<Y>& r, T* p) noexcept;

效果:构造一个shared_ptr实例存储p股所有权r

foo_p不带任何的bar_p->foo所有权,当你调用走样构造,在这种情况下是一个非常好事,因为否则它会尝试delete它破坏。

[util.smartptr.enab]

shared_ptr<T> shared_from_this();

shared_ptr<T const> shared_from_this() const;

要求:[...]须有至少一个拥有&tshared_ptr实例页。

由于bar_p->foo不是由至少一个shared_ptr你最终未定义行为资,GCC抛出bad_weak_ptr但没有义务做任何事情有帮助。

+0

好吧,这就是行为,但这是什么理由?为什么'shared_from_this()'不需要至少有一个'shared_ptr'存储*'p'? – peper0

+0

因为绝对没有办法记住谁拥有一个原始指针以及它计划如何处理它,你似乎认为'shared_ptr'知道或关心'p'的生命周期,更不用说如果它是一部分的可能涉及或可能不涉及另一个'shared_ptr'实例。 – user657267

+0

我认为shared_ptr的别名构造函数只有在'p'的生命周期由'r'保证时(正如'p'指向'r'指向的结构成员的情况一样),才能正确使用。在这种情况下,'shared_ptr'间接关心'p'的生命周期。在其他情况下,'shared_ptr'无论如何都是无效的。 – peper0

相关问题