Q：Binding a callbacks to an expiring shared_ptr?

Q：绑定一个回调即将到期的shared_ptr？

I am familiar with std::shared_ptr and std::weak_ptr and know how they work. However, I would like the std::shared_ptr to emit a callback, like a boost signal. This would allow std::weak_ptr, who still refer to the deleted object, to be cleaned up right in time.

Is there maybe already some smart pointer implementation, which will report the destruction?

Explanation

I think there might be a small design flaw in std::weak_ptrs, that can lead to false memory leaks. By "false memory leak" I mean an object, that is still accessible by the program, but whose reason of existence is not valid anymore. The difference to a true memory leak is, that the true memory leak is completely unknown by the program, while the false leak is just a part that wasn't cleaned up properly.

Another description can be found at codingwisdom.com

Use Watchers

One of the problems with freeing an object is that you may have done so while other things are still pointing at it. This introduces dangling pointers and crashes! To combat the evil of dangling pointers, I like to use a basic "watcher" system. This is not unlike the weak reference discussed above. The implementation is like this:

Create a base class "Watchable" that you derive from on objects that should broadcast when they're being deleted. The Watchable object keeps track of other objects pointing at it.
Create a "Watcher" smart pointer that, when assigned to, adds itself to the list of objects to be informed when its target goes away.

This basic technique will go a long way toward solving dangling pointer issues without sacrificing explicit control over when an object is to be destroyed.

Example

Let's say we implement the observer pattern using boost Boost Signals2. We have a class Observable, that contains one or more signals and another class Observer, that connects to Observable's signals.

What would happen to Observable's slots, when a observing Observer is deleted? When we do nothing, then the connection would point to nowhere and we would probably receive a segmentation fault, when emitting the signal.

To deal with this issue, boost's slots also offer a method track(const weak_ptr<void>& tracked_object). That means, if I call track and pass a weak_ptr to Observer, then the slot won't be called when the weak_ptr expired. Instead, it will be deleted from the signal.

Where is the problem? Let's we delete an Observer and never call a certain signal of Observable ever again. In this case, the tracked connection will also never be deleted. Next time we emit the signal it will be cleaned up. But we don't emit it. So the connection just stays there and wastes resources.

A solution would be: when owning shared_ptr should emit a signal when it is destroying it's object. This would allow other other objects to clean up right in time. Everything that has a weak_ptr to the deleted object might register a callback and false memory leaks could be avoided.

Create a base class "Watchable" that you derive from on objects that should broadcast when they're being deleted. The Watchable object keeps track of other objects pointing at it.
Create a "Watcher" smart pointer that, when assigned to, adds itself to the list of objects to be informed when its target goes away.

This would allow std::weak_ptr, who still refer to the deleted object,
to be cleaned up right in time.

Actually, they only hold weak references, which do not prevent the object from being destroyed. Holding weak_ptrs to an object does not prevent it's destruction or deletion in any fashion.

The quote you've given sounds to me like that guy just doesn't know which objects own which other objects, instead of having a proper ownership hierarchy where it's clearly defined how long everything lives.

As for boost::signals2, that's what a scoped_connection is for- i.e., you're doing it wrong.

The long and short is that there's nothing wrong with the tools in the Standard (except auto_ptr which is broken and bad and we have unique_ptr now). The problem is that you're not using them properly.

This would allow std::weak_ptr, who still refer to the deleted object,
to be cleaned up right in time.

实际上，它们只持有弱引用，不妨碍对象被破坏。控股weak_ptrs对象并不妨碍它以任何方式破坏或缺失。

你给我的引语听起来像那个家伙只是不知道哪一个对象拥有其他对象，而不是有一个适当的所有权层次，它清楚地定义了多久的一切生活。

为提高：：Signals2，那即scoped_connection是什么，你做的不对。

总之，在标准没有错的工具（除了auto_ptr是破坏和我们有unique_ptr现在）。问题是你没有正确使用它们。

answer2：

回答2：

//
// create a C function that does some cleanup or reuse of the object
//
void RecycleFunction
(
MyClass * pObj
)
{
// do some cleanup with pObj
}
//
// when you create your object and assign it to a shared pointer register a cleanup function
//
std::shared_ptr<MyClass> myObj = std::shared_ptr<MyClass>( new MyClass,
RecycleFunction);

Once the last reference expires "RecyleFunction" is called with your object as parameter. I use this pattern to recycle objects and insert them back into a pool.

//
// create a C function that does some cleanup or reuse of the object
//
void RecycleFunction
(
MyClass * pObj
)
{
// do some cleanup with pObj
}
//
// when you create your object and assign it to a shared pointer register a cleanup function
//
std::shared_ptr<MyClass> myObj = std::shared_ptr<MyClass>( new MyClass,
RecycleFunction);