class derived_class : public another_class {};
template <typename T> void intrusive_ptr_add_ref(T* t) {
t->add_ref();
}
template <typename T> void intrusive_ptr_release(T* t) {
if (t->release()<=0) {
t->call_before_destruction();
delete t;
}
}
}
Here, we have implemented generic versions of intrusive_ptr_add_ref and
intrusive_ptr_release. We must therefore remove the generic versions that we
previously put in the global namespace, and replace them with non-templated
versions accepting a pointer to reference_counter as their argument. Or, we could
omit these functions from the global namespace altogether, to avoid cluttering it.
For the two classes my_namespace::another_class and
my_namespace::derived_class, the special version (which calls a member function
call_before_destruction on its arguments) is called. Other types either have
corresponding functions in the namespace where they are defined or use the
version in the global namespace, if it exists. Here's a short program to illustrate
how this works:
int main() {
boost::intrusive_ptr<my_namespace::another_class>
p1(new my_namespace::another_class());
boost::intrusive_ptr<A>
p2(new good_class());
boost::intrusive_ptr<my_namespace::derived_class>
p3(new my_namespace::derived_class());
}
First, the intrusive_ptr p1 is passed a new instance of my_namespace::
must be provided by the classes that are used with intrusive_ptr. intrusive_ptr
manages the reference count by making unqualified calls to two functions,
intrusive_ptr_add_ref and intrusive_ptr_release; these functions must properly
manipulate the intrusive reference count for intrusive_ptrs to work correctly. For
all cases where a reference count already exists
in the types that are to be used with
intrusive_ptr, enabling support for intrusive_ ptr is as easy as implementing those
two functions. In some cases, it's possible to create parameterized versions of those
functions, and have all types with intrusive reference counts use the same
implementation of these functions. In most cases, the best place to declare the
functions is in the same namespace as the types they support.
Use intrusive_ptr when
You need to treat this as a smart pointer.
There is existing code that uses or provides an intrusive reference count.
It is imperative that the size of the smart pointer equals the size of a raw
pointer.
weak_ptr
Header: "boost/weak_ptr.hpp"
A weak_ptr is an observer of a shared_ptr. It does not interfere with the ownership
of what a shared_ptr shares. When a shared_ptr that is being observed by a
weak_ptr must release its resource, it sets the observing weak_ptr's pointer to null.
That prevents the weak_ptr from holding a dangling pointer. Why would you need
a weak_ptr? There are many situations where one needs to observe and use a
shared resource without accepting ownership, such as to break cyclic
dependencies, to observe a shared resource without assuming ownership of it, or to
avoid dangling pointers. It's possible to construct a shared_ptr from a weak_ptr,
thereby gaining access to the shared resource.
Returns TRue if the observed resource has "expired," which means that it has been
released. If the stored pointer is non-null, expired returns false. This function never
throws.
shared_ptr<T> lock() const
Returns a shared_ptr that refers to the resource that this weak_ptr observes, if any.
If there is no such pointer (that is, the weak_ptr refers to the null pointer), the
resulting shared_ptr refers to the null pointer. Otherwise, the reference count for
the resource referenced by the shared_ptr is incremented as usual. This function
never throws.
Usage
We begin with an example that shows the basics of weak_ptrs, and especially
demonstrates how they do not affect the reference counts. Out of necessity, the
examples in this subsection include shared_ptrs as well, because a weak_ptr
always needs to be used together with a shared_ptr. To use weak_ptr, include
"boost/weak_ptr.hpp".
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"
#include <iostream>
#include <cassert>
class A {};
int main() {
boost::weak_ptr<A> w;
assert(w.expired());
{
boost::shared_ptr<A> p(new A());
assert(p.use_count()==1);
w=p;
assert(p.use_count()==w.use_count());
assert(p.use_count()==1);
// Create a shared_ptr from the weak_ptr
A Common Question
Because the ordering of smart pointers doesn't involve the actual values their
pointers are pointing to but the pointer values, a common question with regard to
using these smart pointers in Standard Library containers is how to use algorithms
with the smart pointers; they typically need to access the values of the actual
objects rather than their addresses. For example, how does one call std::sort and
make it perform useful sorting? Actually, the problem is hardly any different from
storing and operating on regular pointers in containers, but that fact is easily
overlooked (probably because storing a raw pointer is so problematic that we tend
to avoid doing it). Out of the box, there is no support for comparing the values of
smart pointers, but that's easy to amend. A typical need is to use predicates that
dereference the smart pointers, so we'll create a reusable predicate that makes it
easy to use the Standard Library algorithms with iterators referencing smart
pointersin this case, weak_ptrs.
#include <functional>
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"
template <typename Func, typename T>
struct weak_ptr_unary_t :
public std::unary_function<boost::weak_ptr<T>,bool> {
T t_;
Func func_;
weak_ptr_unary_t(const Func& func,const T& t)
: t_(t),func_(func) {}
bool operator()(boost::weak_ptr<T> arg) const {
boost::shared_ptr<T> sp=arg.lock();
if (!sp) {
return false;
}
return func_(*sp,t_);
#include "boost/weak_ptr.hpp"
int main() {
using std::string;
using std::vector;
using boost::shared_ptr;
using boost::weak_ptr;
vector<weak_ptr<string> > vec;
shared_ptr<string> sp1(
new string("An example"));
shared_ptr<string> sp2(
new string("of using"));
shared_ptr<string> sp3(
new string("smart pointers and predicates"));
vec.push_back(weak_ptr<string>(sp1));
vec.push_back(weak_ptr<string>(sp2));
vec.push_back(weak_ptr<string>(sp3));
vector<weak_ptr<string> >::iterator
it=std::find_if(vec.begin(),vec.end(),