2

I'm writing some managed handle container, not unsimilar to std::unique_pointer (although I'm not writing my code in C++11 yet). I have something like this:

template <class H>
class UniqueHandle {
    H h;

public:
    UniqueHandle(H _h = 0) // "the first constructor", referred below
        :h(_h) {}

    UniqueHandle(UniqueHandle &other)
        :h(other.YieldOwnership()) {}

    ~UniqueHandle() { ::DeleteHandle(h); }

    UniqueHandle &operator =(UniqueHandle &other)
    {
        ::DeleteHandle(h); // release the old handle
        h = other.YieldOwnership();
        return *this;
    }

    UniqueHandle &operator =(H _h)
    {
        ::DeleteHandle(h); // release the old handle
        h = _h;
        return *this;
    }

    H YieldOwnership() { H result = h; h = 0; return result; }

    operator H() const { return h; }
};

There could be a bunch of other operators, but let's keep it simple. Now let's assume:

typedef int HANDLE;

void DeleteHandle(HANDLE h)
{
    cout << "deleting handle " << h << endl;
}

int main()
{
    UniqueHandle<HANDLE> h(123);
    UniqueHandle<HANDLE> h2 = 456;
    HANDLE unmanaged = 789;
    HANDLE mixed_case = (rand() & 1)? (HANDLE)h : unmanaged;
    DeleteHandle(unmanaged);
    return 0;
}

I've tried running this on ideone, and it works as expected. However, in Visual Studio (2008), the mixed_case does not require the conversion of h to bare HANDLE and instead implicitly converts unmanaged to UniqueHandle<HANDLE>, which causes its deletion shortly after. It took me some time to find this bug, and I know it can be fixed by declaring the first constructor as explicit.

My question is: are the operator = equally dangerous? What other perils one can run into with these types of unique resource managers?

the swine
  • 10,713
  • 7
  • 58
  • 100
  • 3
    Even if you don't use C++11 and its [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/unique_ptr) (or the older [Boost variant](http://www.boost.org/doc/libs/1_56_0/doc/html/boost/interprocess/unique_ptr.html)), you might as well look at it and use it as a reference on how to handle these kind of things. – Some programmer dude Oct 30 '14 at 13:13
  • 1
    Note that if you call the destructor on an object and then continue using it without constructing a new object in its place, you have undefined behaviour. – Angew is no longer proud of SO Oct 30 '14 at 13:14
  • 1
    `std::auto_ptr` was BAD because its copy constructor modified the source object, but at least it was explicit about it (taking a non-const ref). What you're doing is even worse in this regard. – Angew is no longer proud of SO Oct 30 '14 at 13:15
  • @JoachimPileborg I actually did, and that's how I figured out the `explicit`; I actually thought that was not allowed until C++11. But the `std::unique_ptr` does not have `operator =` for raw pointer (except for null). Why? – the swine Oct 30 '14 at 13:15
  • 1
    @theswine Precisely to be explicit about transferring ownership to the `unique_ptr`. It does have `reset()`. – Angew is no longer proud of SO Oct 30 '14 at 13:17
  • @Angew the const-ness of the constructor is a good point. There was a reason for it, I remember, but I don't remember what it was exactly. I think it was something to do with Visual Studio not accepting the non-const one. – the swine Oct 30 '14 at 13:17
  • @Angew I see, to be explicit. But other than that, is there any "unexpected" behavior to be had with `operator =`? – the swine Oct 30 '14 at 13:23
  • @Angew btw it is perfectly legal to call the destructor, and since in this case it only deletes the handle (it does not `delete this`), it is not a problem (see http://stackoverflow.com/questions/16720201/calling-destructor-explicitly). – the swine Oct 30 '14 at 13:25
  • 1
    @theswine It's indeed legal to call the dtor, but it is *not* legal to keep using the object after that. See C++11 3.8/5 – Angew is no longer proud of SO Oct 30 '14 at 13:32
  • @Angew I see. That must be a new rule in C++11. – the swine Oct 30 '14 at 13:36
  • @theswine Nope, exactly the same section nr. in C++03 as well. – Angew is no longer proud of SO Oct 30 '14 at 13:38

0 Answers0