Search code examples
c++shared-ptrsmart-pointerstr1reference-counting

using std::tr1::shared_ptr as an internal mechanism for reference counting


Is it safe and correct to use an std::tr1::shared_ptr as in the sample code below, for the purpose of reference counting? (this is just a particular sample, the class can contain anything else (void*) instead of the FILE*)

class File
{
public:
    File(const char* path, const char* mode) :
        _refcount(new int(0))
    {
        this->_file = fopen(path, mode);
    }

    ~File()
    {
        if (this->_refcount.unique())
        {
            if (this->_file != NULL)
            {
                fclose(this->_file);
            }
        }
    }

    int write(void* buff, size_t size)
    {
        fwrite(buff, size, 1, this->_file);
    }

private:
    FILE* _file;
    std::tr1::shared_ptr<int> _refcount;
};

Solution

  • Consider instead using a shared_ptr<FILE> with a custom deleter:

    struct fclose_deleter
    {
        void operator()(FILE* f)
        {
            if (f)
            {
                std::fclose(f);
            }
        }
    };
    

    Then, your File class is much simpler (and correcter):

    class File
    {
    public:
        File(const char* path, const char* mode)
            : _file(std::fopen(path, mode), fclose_deleter())
        {
        }
    
        int write(void const* buff, size_t size)
        {
            // You'll want to verify that _file.get() is valid, or you'll want to
            // throw in the constructor if the call to 'std::fopen()' fails.
            std::fwrite(buff, size, 1, _file.get());
        }
    
    private:
        std::tr1::shared_ptr<FILE> _file;
    };