title: Ref counted smart pointer's assignment operator
body: <p>despite the ocean of smart pointer questions out there, I seem to be stuck with one more. I am trying to implement a ref counted smart pointer, but when I try it in the following case, the ref count is wrong. The comments are what I think should be the correct ref counts.</p>
  
  <pre><code>Sptr&lt;B&gt; bp1(new B);       // obj1: ref count = 1
  Sptr&lt;B&gt; bp2 = bp1;        // obj1: ref count = 2
  bp2 = new B;              // obj1: ref count = 1, obj2: rec count = 1 **problem**
  </code></pre>
  
  <p>In my implementation, my obj2 ref count is 2, because of this code:</p>
  
  <pre><code>protected:
      void retain() { 
          ++(*_rc);
          std::cout &lt;&lt; "retained, rc: " &lt;&lt; *_rc &lt;&lt; std::endl;
      }
      void release() {
          --(*_rc);
          std::cout &lt;&lt; "released, rc: " &lt;&lt; *_rc &lt;&lt; std::endl;
          if (*_rc == 0) {
              std::cout &lt;&lt; "rc = 0, deleting obj" &lt;&lt; std::endl;
              delete _ptr;
              _ptr = 0;
              delete _rc;
              _rc = 0;
          }
      }
  
  private:
      T *_ptr;
      int *_rc;
  
      // Delegate private copy constructor
      template &lt;typename U&gt;
      Sptr(const Sptr&lt;U&gt; *p) : _ptr(p-&gt;get()), _rc(p-&gt;rc()) {
          if (p-&gt;get() != 0) retain();
      }
  
      // Delegate private assignment operator
      template &lt;typename U&gt;
      Sptr&lt;T&gt; &amp;operator=(const Sptr&lt;U&gt; *p) {
          if (_ptr != 0) release();
          _ptr = p-&gt;get();
          _rc = p-&gt;rc();
          if (_ptr != 0) retain();
          return *this;
      }
  
  public:
      Sptr() : _ptr(0) {}
      template &lt;typename U&gt;
      Sptr(U *p) : _ptr(p) { _rc = new int(1); }
  
      // Normal and template copy constructors both delegate to private
      Sptr(const Sptr &amp;o) : Sptr(&amp;o) {
          std::cout &lt;&lt; "non-templated copy ctor" &lt;&lt; std::endl;
      }
      template &lt;typename U&gt;
      Sptr(const Sptr&lt;U&gt; &amp;o) : Sptr(&amp;o) {
          std::cout &lt;&lt; "templated copy ctor" &lt;&lt; std::endl;
      }
  
  
      // Normal and template assignment operator
      Sptr &amp;operator=(const Sptr &amp;o) {
          std::cout &lt;&lt; "non-templated assignment operator" &lt;&lt; std::endl;
          return operator=(&amp;o);
      }
      template &lt;typename U&gt;
      Sptr&lt;T&gt; &amp;operator=(const Sptr&lt;U&gt; &amp;o) {
          std::cout &lt;&lt; "templated assignment operator" &lt;&lt; std::endl;          
          return operator=(&amp;o);
      }
      // Assignment operator for assigning to void or 0
      void operator=(int) {
          if (_ptr != 0) release();
          _ptr = 0;
          _rc = 0;
      }
  </code></pre>
  
  <p>The constructor is initialized with a ref count = 1, but in my assignment operator, I am retaining the object, making the ref count = 2. But it should only be 1 in this case, because bp2 = new B is only one pointer to that object. I've looked over various smart pointer implementation examples, and I can't seem to figure out how they deal with this case that I'm having trouble with.</p>
  
  <p>Thanks for your time!</p>