4
一些智能指針模板,如boost :: shared_ptr的,可以用空實例化持有任意對象:如何實現可以用void實例化的智能指針?
http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/sp_techniques.html#pvoid
下面是一個最小的scoped_ptr的實現。當用void實例化時,編譯器會抱怨在解引用操作符中形成了一個非法的「引用void」。看起來「替代失敗不是一個錯誤」(SFINAE)規則並不包括這種情況。
那麼如何實現scoped_ptr?特別是,有沒有替代寫作模板專業化?這會導致實際的智能指針實現導致大量的代碼重複。
#include <cstdlib>
template<typename T>
void destroy(T* ptr)
{
delete ptr;
}
class scoped_ptr_impl_base
{
public:
virtual ~scoped_ptr_impl_base() { }
};
template<typename T, typename F>
class scoped_ptr_impl : public scoped_ptr_impl_base
{
public:
scoped_ptr_impl(T* ptr, F dtor)
: m_ptr(ptr), m_dtor(dtor)
{
}
virtual ~scoped_ptr_impl()
{
m_dtor(m_ptr);
}
private:
T* m_ptr;
F m_dtor;
};
template<typename T>
class scoped_ptr
{
public:
explicit scoped_ptr(T* ptr = 0)
: m_ptr(ptr),
m_impl(new scoped_ptr_impl<T, void (*)(T*)>(&destroy<T>))
{
}
template<typename F>
scoped_ptr(T* ptr, F dtor)
: m_ptr(ptr),
m_impl(new scoped_ptr_impl<T, F>(ptr, dtor))
{
}
~scoped_ptr()
{
delete m_impl;
}
T& operator*()
{
return *m_ptr;
}
T* operator->()
{
return m_ptr;
}
private:
T* m_ptr;
scoped_ptr_impl_base* m_impl;
scoped_ptr(const scoped_ptr&);
scoped_ptr& operator=(const scoped_ptr&);
};
int main()
{
scoped_ptr<void> p(std::malloc(1), std::free);
// scoped_ptr.cpp: In instantiation of `scoped_ptr<void>':
// scoped_ptr.cpp:76: instantiated from here
// scoped_ptr.cpp:56: error: forming reference to void
// (g++ 4.3.3)
return 0;
}
+1。我更喜歡「空洞」。如果你能解引用一個無效指針,你會得到什麼。無論如何,這可能並不重要,因爲只要他試圖調用operator *,他就會得到一個關於解除引用void *的錯誤。 – 2009-08-21 15:37:33
是的,void絕對比void *更好,因爲如果你嘗試解引用'shared_ptr'(這應該被認爲是錯誤),它會導致錯誤。 –
2009-08-21 15:39:41
同意,把它改回來。總是去你的第一本能...... – 2009-08-21 15:43:13