Piszę kod inteligentnych wskaźników jako ćwiczenie. Korzystanie z samouczków online (1, 2) Opracowałem normalną klasę inteligentnych wskaźników z licznikiem odwołań. Problemem jest to, nie jestem w stanie dowiedzieć się, co następuje:Unikaj krojenia obiektów dla nie-wirtualnych destruktorów.
gdy inteligentny wskaźnik wykryje, że nie ma więcej odniesień istnieć do danego obiektu, należy go usunąć obiekt za pomocą wskaźnika do samego typu, nawet jeśli argument szablonu ostatecznego wskaźnika inteligentnego jest typu podstawowego. Ma to na celu uniknięcie krojów obiektów dla nie-wirtualnych destruktorów.
Jak mogę to osiągnąć. Zasadniczo mój kod wygląda jak poniżej (z samouczka).
template < typename T > class SP
{
private:
T* pData; // pointer
RC* reference; // Reference count
public:
SP() : pData(0), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(T* pValue) : pData(pValue), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)
{
// Copy constructor
// Copy the data and reference pointer
// and increment the reference count
reference->AddRef();
}
~SP()
{
// Destructor
// Decrement the reference count
// if reference become zero delete the data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
}
T& operator*()
{
return *pData;
}
T* operator->()
{
return pData;
}
SP<T>& operator = (const SP<T>& sp)
{
// Assignment operator
if (this != &sp) // Avoid self assignment
{
// Decrement the old reference count
// if reference become zero delete the old data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
// Copy the data and reference pointer
// and increment the reference count
pData = sp.pData;
reference = sp.reference;
reference->AddRef();
}
return *this;
}
};
EDIT:
Aby to osiągnąć muszę mieć wskaźnik do typu oryginału.
I napisali tutaj pytanie: delete via a pointer to Derived, not Base
ale teraz od przeglądania komentarzy i odpowiedzi Myślę, że obie są powiązane. Mam konstruktora:
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
//do something
ref = new RC();
ref->AddRef();
}
Rozważmy teraz Sptr<Base1> sp(new Derived);
gdzie Derived
pochodzi z Base1
. Baza1 ma chroniony konstruktor/destruktor. Który jest przechowywanie dla obiektu typu T
Ale muszę przechowywać go za pośrednictwem obiektu typu U. Muszę zachować to. Jak mogę to zrobić?
Jeśli klasa bazowa nie ma wirtualnego destruktora, a ktoś próbuje usunąć pochodną klasę przez wskaźnik do tej klasy bazowej, to ktoś robi to źle. – Chad
Aby to osiągnąć, musisz nadać 'SP' konstruktorowi szablonu' SP :: SP (U * u) {...} 'i jakoś przechowywać oryginalny typ' U' (który musi pochodzić od ' T'), aby móc później wywołać destruktor 'U'. –
Angew
Czy C++ 11 stwierdza, że inteligentny wskaźnik zgodny musi to zrobić? Wygląda na to, że 'std :: unique_ptr' nie: http://ideone.com/iyanmY – Chad