聪明的指针--为什么要使用它们,应该使用哪种?
一般问题
现在我读了很多关于智能指针的文章,在很多情况下,共享指针似乎是"完美的"。然而,我也读到了周期性引用或类似的东西?哪里不能使用shared_ptr
?我很难理解这一点,有谁能举一个简单的例子来说明这一点吗?
我真的想知道,弱_ptr提供了什么普通指针不能提供的?-因为它们不增加引用计数,所以它们不能保证它们所指向的内存仍然有效?
我的个人项目:
在一个项目中,我有两个"全局"容器(这两个容器很快都会移动到一个类中),它们都填充了"对象"。然而,两者都应该"指向"相同的对象。对象不能存在于这些容器之外,而且不可能一个容器包含该对象,而另一个容器不包含该对象。
目前我只是简单地使用普通指针来管理内存,并且有一个createObject
&;destroyObject
方法来管理内存。
这个设计好吗?我是否应该使用智能指针?
解决方案
回答您的各种问题:
循环引用是指两个不同的对象各自具有指向另一个对象的Shared_PTR。
例如:
struct Foo {
shared_ptr< Bar > m_bar;
};
struct Bar {
shared_ptr< Foo > m_foo;
};
void createObject()
{
shared_ptr< Foo > foo( new Foo );
shared_ptr< Bar > bar( new Bar );
foo->m_bar = bar;
bar->m_foo = foo;
//Neither of these objects will be released here
}
这可能会导致两个对象都不会被释放,因为foo将始终将对bar的引用计数保持在1以上,而foo将不会被释放,因为bar将始终将其引用计数保持在1以上。
这是一种可以使用WARNCE_PTR克服的情况,因为它们不会增加引用计数。正如您所指出的,这不会阻止释放PTR,但确实允许您在使用对象之前检查对象是否仍然存在,这是使用标准指针所做不到的。 对于您提供的示例,您几乎应该始终使用智能指针而不是原始指针,因为它们允许对象在超出作用域时自动释放,而不是您必须确保它是自己完成的,这很容易出错。在您有异常的情况下尤其如此,它可以很容易地跳过您编写的任何发布代码。例如,以下代码可能会导致问题:
Foo* foo = createObject();
foo.doSomething();
deleteObject( foo );
如果foo.doSomething为Except,则将永远不会调用DeleteObject,并且Foo将不会被释放。
但是,这将是安全的:
shared_ptr< Foo > foo = createObject();
foo.doSomething();
无论是否发生异常,Shared_ptr都将在代码块末尾自动释放。
这里很好地讨论了指针和智能指针:Pointers, smart pointers or shared pointers?
相关文章