我正在编写一些托管句柄容器,与std::unique_pointer
(尽管我还没有在 C++11 中编写我的代码)不同。我有这样的事情:
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; }
};
可能还有很多其他运算符,但让我们保持简单。现在让我们假设:
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;
}
我试过在ideone上运行它,它按预期工作。但是,在 Visual Studio (2008) 中,mixed_case
不需要转换h
为 bareHANDLE
而是隐式转换unmanaged
为UniqueHandle<HANDLE>
,这会导致它在不久之后被删除。我花了一些时间才找到这个错误,我知道可以通过将第一个构造函数声明为explicit
.
我的问题是:operator =
同样危险吗?使用这些类型的独特资源管理器还会遇到哪些其他危险?