我正在阅读" C ++标准库" Nicolai M. Josuttis的书,用于理解弱点。作者提到了需要有一个weak_ptr的两个原因而我没有得到第二个原因。任何人都可以提供一个简单的解释以及以下原因的例子(引自书中):
当您明确想要共享但不拥有对象时,会出现另一个示例。因此,您具有以下语义:对对象的引用的生命周期超过它引用的对象。在这里,shared_ptrs永远不会释放对象,普通指针可能不会注意到它们引用的对象不再有效,这会带来访问已发布数据的风险。
答案 0 :(得分:8)
该语句的后半部分应该是明确的:如果指针不是拥有指针,那么它指向的对象可能会被 的任何软件删除。所有者 - 然后你就会有标准的悬空参考。
所以这个问题是:你有一些软件拥有的对象让其他软件可以访问它 - 但是其他软件不会共享所有权。所以所有者可以随时删除它,而其他软件需要知道它的指针不再有效。
也许一个例子会有所帮助:
你有一些软件正在观看一个摄像头,指出你的窗户指向一个喂鸟器,它正在识别喂食器上的鸟类,它来来去去。进给器中的每只鸟在到达进纸器时都有一个由该软件创建的对象,当该鸟飞走时该对象被删除。
与此同时,其他一些软件正在进行人口普查。它每隔10秒就从喂食器观察软件中抓取一个喂食器上的鸟类。每隔100秒就会发出一个报告,说明哪些鸟在整个100秒内都在进料器上。
因为鸟类的数据很大,人口普查员不会复制数据。它只是每隔10秒从馈线观察者那里得到一组指针。
为了有必要使用弱指针,让我们说喂食者观察者只提供指向过去十秒内到达的鸟类的指针,而不是那些曾经到过的指针。也就是说,没有通知鸟类已经消失。
通过使用弱指针,它可以在报告时知道哪些鸟仍在那里,何时到达(但不是在他们离开时)。
(也许我稍后会想到一个更好的例子。)
答案 1 :(得分:4)
想象一个假想的计时器事件源的回调函数
struct my_thing : std::enable_shared_from_this<my_thing>
{
void start()
{
auto weak_self = std::weak_ptr<my_thing>(shared_from_this());
_timer.set_callback([weak_self] {
if (auto self = weak_self.lock()) {
self->respond_to_timer();
}
});
}
void respond_to_timer()
{
// do something here
}
SomeTimer _timer;
};
在上面的示例中,my_thing
拥有计时器,但计时器已经获得了一个引用my_thing
的回调。这将是一个循环引用,可以防止my_thing
被删除。
使用weak_self
weak_ptr打破了循环所有权问题。
答案 2 :(得分:2)
e.g:
struct node
{
std::shared_ptr<node> left_child;
std::shared_ptr<node> right_child;
std::weak_ptr<node> parent;
foo data;
};
在此示例中,删除节点将删除left_child和right_child,但不删除父节点。如果由于某种原因,节点比父节点更长,并且父节点被删除,则可以知道父节点不再有效。 (假设您没有引用left_child或right_child与另一个shared_ptr)