简体   繁体   中英

Implementing Smart Pointer - storing template class in vector

I'm having trouble storing instances of my smart pointer into a container. Here is the code for the pointer.

#include "std_lib_facilities.h"

template <class T>
class counted_ptr{
private:
    T* pointer;
    int* count;

public:
    counted_ptr(T* p = 0, int* c = new int(1)) : pointer(p), count(c) {}    // default constructor
    explicit counted_ptr(const counted_ptr& p) : pointer(p.pointer), count(p.count) { ++*count; } // copy constructor
    ~counted_ptr()
    {
        --*count;
        if(!*count) {
            delete pointer;
            delete count;
        }
    }

    counted_ptr& operator=(const counted_ptr& p)    // copy assignment
    {
        pointer = p.pointer;
        count = p.count;
        ++*count;
        return *this;
    }
    T* operator->() const{ return pointer; }
    T& operator*() const { return *pointer; }
    int& operator[](int index) { return pointer[index]; }

    int Get_count() const { return *count; }    // public accessor for count


};




int main()
{
    counted_ptr<double>one;
    counted_ptr<double>two(one);
    one = new double(5);
    vector<counted_ptr<double> >test;
}

In int main(), the vector<counted_ptr<double> > line does compile. When I first tried it with just vector<counted_ptr<double> > it didn't compile (probably because it was lacking parameters.) However, when I try to use push_back such as

test.push_back(one);

I get a compiler error that opens up vector.tcc with the specific error saying that

no matching function for call to `counted_ptr<double>::counted_ptr(const counted_ptr<double>&)'|

I'm guessing that push_back can't find a counted_ptr, but I'm really not sure. Any help is appreciated, thanks.

Edit: However, this works. test[0] = one; I guess the semantics of push_back are what is restricting it.

You may want to try this:

test.push_back(counted_ptr<double>(one));

You copy constructor is explicit which means that the compiler won't implicitly invoke it.

Personally, I would make the raw pointer constructor explicit and the copy ctor not explicit. That would be closer to usual behavior.

EDIT: I also recommend that you implement a swap method. It makes assignment absolutely trivial. You end up with something like this:

counted_ptr &operator=(const counted_ptr &rhs) {
    counted_ptr(rhs).swap(*this);
    return *this;
}

This also has the benefit of all of the accounting happening in constructors/destructors which is a lot simpler to manage :-).

Your assignment operator is wrong.
What happened to the object it was pointing at?
What happens if you are assigning to yourself or the same internal object?

counted_ptr& operator=(const counted_ptr& p)    // copy assignment
{
    if (&p != this)
    {
        --*count;
        if ((*count) == 0) // Much more readable than !*count
        {
            delete pointer;
            delete count;
        }
        pointer = p.pointer;
        count = p.count;
        ++*count;
    }
    return *this;
}

Note: Writing your own smart pointer is not a good idea. They are not as trivial to write as you think.

Note: This is the first thing I spotted. There could be more, and I am not sure this is 100% correct.

In fact I would change the assignment operator to use copy/swap idium.

counted_ptr& operator=(const counted_ptr& p)    // copy assignment
{
    counted_ptr<T>     tmp(p);   // increment counter on p
    swap(tmp.pointer, pointer);
    swap(tmp.count    count);

    return *this;
                                 // tmp goes out of scope and thus the
                                 // destructor gets called and what was in this
                                 // object is now destroyed correctly.
}
// It may even be worth writing your own swap operator.
// Make sure you declare it as no-throw and grantee it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM