title: How to use Boost's intrusive_ptr effectively?
body: <h2>Manual Unref</h2>
  
  <p>I have an issue with Boost's intrusive pointer. It's <a href="http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/intrusive_ptr.html#conversions" rel="nofollow noreferrer">boolean conversion operator</a> checks <code>x.get() != 0</code>. However, the code below fails at the marked point. Why is this the case?</p>
  
  <p>I am guessing that I may have to do with the fact that <a href="https://stackoverflow.com/q/5002055/1170277"><code>delete</code> does not set a pointer to <code>0</code></a> (or <code>nullptr</code>). If that's not the case, how could I use the intrusive pointer effectively? I would like to be able to use an intrusive pointer like a regular pointer, e.g., in an expression <code>x &amp;&amp; x-&gt;foo()</code>, but this artefact seems to preclude it.</p>
  
  <pre><code>#include &lt;atomic&gt;
  #include &lt;boost/intrusive_ptr.hpp&gt;
  
  struct T
  {
      T() : count(0u) { }
  
      size_t ref_count()
      {
          return count;
      }
  
      std::atomic_size_t count;
  };
  
  void intrusive_ptr_add_ref(T* p)
  {
      ++p-&gt;count;
  }
  
  void intrusive_ptr_release(T* p)
  {
      if (--p-&gt;count == 0u)
          delete p;
  }
  
  int main()
  {
      boost::intrusive_ptr&lt;T&gt; x;
      x = new T;
      assert(x-&gt;ref_count() == 1);
  
      auto raw = x.get();
      intrusive_ptr_add_ref(raw);
      intrusive_ptr_add_ref(raw);
      assert(x-&gt;ref_count() == 3);
  
      intrusive_ptr_release(raw);
      intrusive_ptr_release(raw);
      assert(x-&gt;ref_count() == 1);
  
      intrusive_ptr_release(raw); // Destroys T, ref_count() == 0.
      assert(! x); // Fails.
  
      return 0;
  }
  </code></pre>
  
  <p>(Architecture: Darwin 10.7, tested compilers g++ 4.7 and 4.6 with <code>-std=c++11</code>)</p>
  
  <h2>Reference-to-Pointer</h2>
  
  <p>After weeding through the source code of <code>intrusive_ptr&lt;T&gt;</code>, I found that there is only one call to <code>intrusive_ptr_release</code> in the destructor:</p>
  
  <pre><code>~intrusive_ptr()
  {
      if( px != 0 ) intrusive_ptr_release( px );
  }
  </code></pre>
  
  <p>Since the argument <code>px</code> of type <code>T*</code> is an lvalue, it should be possible to set it to zero by slightly changing the function signature of <code>intrusive_ptr_release</code>:</p>
  
  <pre><code>inline void intrusive_ptr_release(T*&amp; p)
  {
      if (--p-&gt;count == 0u)
      {
          delete p;
          p = 0;
      }
  }
  </code></pre>
  
  <p>Intuitively, this pointer reference-to-pointer parameter should assign the lvalue of <code>p</code> in the calling context to 0. Bjarne also <a href="http://www.stroustrup.com/bs_faq2.html#delete-zero" rel="nofollow noreferrer">mentions this idiom</a>. However, the assertion still fails at the marked line, leaving me clueless this time.</p>
  
  <h2>Example Usage</h2>
  
  <p>The reason why I am ref'ing and unref'ing the pointer manually is that I have to work with the raw pointer for a while when passing it to a C API. This means I have to ref it before passing it to the C API in order to prevent destruction, and recreate an intrusive pointer from the raw pointer when I get it back. Here is an example:</p>
  
  <pre><code>void f()
  {
      intrusive_ptr&lt;T&gt; x = new T;
      auto raw = x.get();
      intrusive_ptr_add_ref(raw);
      api_in(raw);
  }
  
  void g()
  {
      T* raw = api_out();
      intrusive_ptr&lt;T&gt; y(raw, false);
      h(y);
  }
  </code></pre>
  
  <p>Here, the second parameter in the construction of <code>y</code> in <code>g()</code> avoids a ref when getting the pointer back from the C API, which compensates for the manual ref in <code>f()</code>.</p>
  
  <p>I realized that manually unreffing an intrusive pointer can lead to unexpected behavior, whereas this usage appears to be fine.</p>