为什么用它们,用哪一个
why use them, and which to use?
一般问题
现在我读了很多关于智能指针的文章,在很多情况下,共享指针似乎是"完美的"。但是我也读到过循环参考之类的东西?不能使用shared_ptr
的地方?我很难理解这个,谁能举个简单的例子来说明这个?
我也很想知道,weak_ptr提供了什么普通指针没有的?由于他们不增加引用计数,他们不能保证他们指向的内存仍然有效?
个人项目:
在一个项目中,我有2个"全局"容器(两个容器很快就会被移动到类中),两者都充满了"对象"。然而,两者都应该"指向"同一个对象。一个对象不能存在于这些容器之外,并且不应该出现一个容器包含它而另一个容器不包含它的情况。
目前我只是使用普通指针,并有一个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。
这种情况可以用weak_ptr来克服,因为它们不增加引用计数。正如您所指出的,这不会阻止ptr被释放,但允许您在使用它之前检查对象是否仍然存在,这是使用标准指针无法做到的。
对于您提供的示例,您应该几乎总是使用智能指针而不是原始指针,因为它们允许对象在超出作用域时自动释放,而不是您必须确保自己完成它,这可能容易出错。在有异常的情况下尤其如此,异常可以很容易地跳过您编写的任何发布代码。
例如,下面的代码可能会导致问题:
Foo* foo = createObject();
foo.doSomething();
deleteObject( foo );
如果foo。doSomething是except,那么deleteObject永远不会被调用,foo也不会被释放。
但是,这是安全的:
shared_ptr< Foo > foo = createObject();
foo.doSomething();
shared_ptr将在代码块结束时自动释放,无论是否发生异常。
这里有一个关于指针和智能指针的很好的讨论:指针,智能指针还是共享指针?
这里有一个简单的循环引用的例子:
struct Node {
shared_ptr<Node> next;
};
int main()
{
shared_ptr<Node> n1(new Node), n2(new Node);
n1->next = n2;
n2->next = n1;
}
n1
和n2
相互指向,形成一个循环。香草shared_ptr
应该只用于有向无环图(dag)。对于循环,有weak_ptr
,它不会在循环时搞砸引用计数,但应该小心使用。DAG或树结构中的反向指针是weak_ptr
的有效用例,允许您在结构中进行备份。
关于你当前的项目:是的,试试shared_ptr
,它可能会让你的生活更容易。你可以用use_count() >= 2
来检查一个对象是否存在于两个容器中;请注意>=2
,因为您可能会将指向所包含对象的指针传递给客户机代码,这会增加引用计数。
如果你使用shared_ptr,你最终会得到一圈指针,例如p1 -> p2 -> p3 -> p1,然后它们永远不会被释放。要打破这个循环,你可以使用weak_ptr,例如:P1 sp-> p2 sp-> p3 wp-> P1,然后自动释放共享指针
要记住的是,尽管智能指针使您不必记住显式地删除资源,但它们并不是灵丹妙药,您仍然可以获得内存"泄漏",例如当您有一圈指针时,并且在复杂的系统中,它们可能同样难以追踪。
对于协调两个不同容器的特定问题,一种方法是将两个容器捆绑在一个类中,以保持这种不变性。
另一个是使用Boost.MultiIndex
,它已经提供了这种保证。需要一些实践,我仍然建议使用相关方法包装访问,以便为用户提供以业务为中心的界面。
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 替换密码:哪一个?
- For-loop或std::any_of,我应该使用哪一个?
- 哪一个是最好的方法类或结构?在 C++ 中
- 静态常量与常量局部变量,哪一个性能更好
- 一个互斥锁与多个互斥锁.哪一个更适合线程池?
- cv::String 和 std::string:何时使用哪一个以及必须同时使用两者?
- 哪一个对物体检测更快?
- 哪一个更适合存储字符、矢量<char>或字符串?
- Visual C++ 和 gcc 之间从 std::isblank 返回不一致.哪一个错了
- 在 C 和 C++ 编程中使用哪一个更好?
- 这两者中的哪一个是实现标头的正确方法
- 带大小参数和不带大小参数的"运算符删除":当两者都可用时,选择哪一个?
- C++编译器在封装行为上存在分歧 - 哪一个做对了?
- 对于初学者来说,我应该学习" c or c++ "之间的哪一个才能使用Arduino UNO?
- MongoC ++驱动程序BSON构造:基于流与基于字符串解析.哪一个性能更好?
- 我应该使用哪一个以及为什么:{} vs = 在 C++ 中
- 哪一个更快,为什么?1.阵列2.链接列表.如果我们只想在for循环中迭代并打印它
- 为什么用它们,用哪一个