Skip to main content
2 of 4
added 164 characters in body
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

OK. Lets ignore that you are screwing around with mutable.

###No Strong Exception Guarantee.

void pass(T* ptr = NULL)
{
    if (p != ptr)
    {
        delete[] p;   // if p throws then your object is left in
                      // an invalid state and you have leaked the
                      // pointer `ptr`
        p = ptr;
    }
}

You should do this in an exception safe way. Which requires the use of a temporary.

void pass(T* ptr = NULL)
{
    if (p != ptr)
    {
        T* tmp = p;
        p = ptr;
        delete[] tmp;   // now it is safe to delete.
                        // even if it throws this object is consistent
                        // and you have not leaked ptr.
    }
}

###Double ownership check

Both this method and the previous check for self assignment. Because this function calls the above function you perform a self assignment check twice when you use the assignment operator.

owner_ptr& operator=(const owner_ptr<T>& rhs)
{
    if (this != &rhs)  // Check here
    {
        this->pass(rhs.get_ownership());  // Check inside pass()
    }
    return *this;
}

I would change both of these methods to call a private method that does the check and work.

owner_ptr& operator=(const owner_ptr<T[]>& rhs)
{
    private_pass(rhs.get_ownership());
}

void pass(T* ptr = NULL)
{
    private_pass(ptr);
}
private:
void private_pass(T* ptr)
{
    if (p != ptr)
    {
        T* tmp = p;
        p = ptr;
        delete[] tmp;
    }
}

###No Throwing methods

Since the get_ownership() method is guaranteed not to throw you should probably mark it as such.

T* get_ownership() throws();

###Questions:

Is it a bad idea to use mutable to solve the ownership-passing problem?

Probably. Mutable is really for designating members that are not part of the objects actual state (ie temporary caches).

Are there any scenarios where it can cause undefined behaviour?

Don't think so. You will just loose out on certain optimizations.

Is there anything that I implemented incorrectly in the template?

Don't see anything.

Any affect on performance?

Yes. As noted above the compiler can not apply certain optimizations when a member is marked mutable.

Before C++11, why did we have only the silly std::auto_ptr which couldn't be used with std::vector?

Because the language did not have the features required to implement modern smart pointers. The auto_ptr was the first attempt at a smart pointer and it worked to a certain extent it just had limitations.

It took them 8 years to improve the language enough so that smart pointers could be implemented properly.

Loki Astari
  • 97.7k
  • 5
  • 126
  • 341