Удаление объекта из метода его класса

Ситуация такая, есть класс Thread, который запускает поток, исполняющая функция потока - метод run() передаваемого класса:
MyServer* server = new MyServer(clientSock);Thread serverThread(server);serverThread.start();
server общается с клиентом через переданный после accept'a сокет clientSock. Т.к. заранее неизвестно когда данная сессия окончится, то было найдено такое решение удаления объекта MyServer:
void MyServer::run() {...delete this;}
Корректно ли такое удаление объекта? Может следует как-то иначе организовать этот код?P.S. Используемый компиллятор g++-4.2.1P.P.S. Собственный сборщик мусора запоминанием указателя server и последующей проверкой... не хочется делать...
4 ответа

boost::shared_ptr<MyServer> server(new MyServer(clientSock));Thread serverThread(server.get());//лучше переписать параметр под shared_ptrserverThread.start();


Действительно, vinter прав. Лучше использовать какую-либо разновидность указателя с подсчетом ссылок.Удалять объект в собственном методе в принципе можно, но легко нарваться: нужно гарантировать, что после delete уже не будет никакого кода, который обращается к объекту. А это очень легко нарушить, например, переопределив в наследнике метод, и т.д.  Более того, такое нарушение может некоторое время нормально работать, и вылезет после изменения программы где-то в совершенно другом месте. 


Т.е. как я понял, большинство за нагроможденный вариант с отслеживанием состояния потока и последующим удалением объекта по факту завершения потока?To Vinter: использование стороннних библиотек типа Boost в данном проекте, увы, исключено.To Earnest: Не очень красивый вариант, но за неимением лучшего... можно сделать все методы MyServer приватными и frend'ом класс Thread для вызова run(), что исключит проблемы с вызовом несуществующего объекта.


Для объектов, которые сами могут принимать решение о собственном уничтожении, я когда-то создавал специальные вспомогательные классы:
// Bool.h#ifndef BOOL_H_#define BOOL_H_#undef Bool#undef True#undef Falsestruct BoolStruct { int field; };typedef int BoolStruct::*Bool;inline Bool False() { return 0; }inline Bool True()  { return &BoolStruct::field; }template <class T>    Bool GetBool(const T &t)        { return t ? True() : False(); }#endif
// SelfDestructive.h#ifndef SELF_DESTRUCTIVE_H_#define SELF_DESTRUCTIVE_H_#include "Bool.h"class SelfDestructive{protected:    SelfDestructive() : info(0) {}    inline virtual ~SelfDestructive() = 0;    void Destroy() { if (info) info->Destroy(); }    bool CanSelfDestruct() const { return info!=0; }private:    struct PtrInfo    {        SelfDestructive *p;        int nRefs;        PtrInfo(SelfDestructive *p) : p(p), nRefs(1) {}        void Destroy() { delete p; p = 0; }    } *info;    template <class T>        friend class SdPtr;};template <class T>    class SdPtr{public:    explicit SdPtr(T *pSelfDestructive = 0);    SdPtr(const SdPtr &a);    template <class T_>        SdPtr(const SdPtr<T_> &a);    ~SdPtr() { DestroyRef(); }    SdPtr &operator =(const SdPtr &a) { return operator = <T>(a); }    template <class T_>        SdPtr &operator =(const SdPtr<T_> &a);    operator Bool() const    { return GetBool(p && info->p); }    int UseCount() const    { return p ? info->nRefs() : 0; }    T &operator *() const    { return *p; }    T *operator ->() const    { return p; }    T *Ptr() const            { return *this ? p : 0; }    void Reset()            { DestroyRef(); p=0; }    void Set(T *pSelfDestructive);    void swap(SdPtr &a)    { std::swap(p, a.p); std::swap(info, a.info); }    SdPtr &lvalue()        { return *this; }private:    typedef SelfDestructive::PtrInfo PtrInfo;    T *p;    PtrInfo *info;    static PtrInfo *CreateInfo(T *p);    void DestroyRef();    template <class T_>        friend class SdPtr;};template <class T1, class T2>    bool operator ==(const SdPtr<T1> &a1, const SdPtr<T2> &a2)        { return a1.Ptr()==a2.Ptr(); }template <class T1, class T2>    bool operator ==(const SdPtr<T1> &a, T2 *p)        { return a.Ptr()==p; }template <class T1, class T2>    bool operator ==(T1 *p, const SdPtr<T2> &a)        { return p==a.Ptr(); }template <class T1, class T2>    bool operator !=(const SdPtr<T1> &a1, const SdPtr<T2> &a2)        { return a1.Ptr()!=a2.Ptr(); }template <class T1, class T2>    bool operator !=(const SdPtr<T1> &a, T2 *p)        { return a.Ptr()!=p; }template <class T1, class T2>    bool operator !=(T1 *p, const SdPtr<T2> &a)        { return p!=a.Ptr(); }#include "SelfDestructive.hxx"#endif
// SelfDestructive.hxxinline SelfDestructive::~SelfDestructive() {}template <class T>    SdPtr<T>::SdPtr(T *pSelfDestructive) : p(pSelfDestructive), info(CreateInfo(p))        { if (p) p->SelfDestructive::info = info; }template <class T>    SdPtr<T>::SdPtr(const SdPtr<T> &a){    if (a)        p = a.p, info = a.info, ++info->nRefs;    else        p = 0, info = 0;}template <class T>    template <class T_>        SdPtr<T>::SdPtr(const SdPtr<T_> &a){    if (a)        p = a.p, info = a.info, ++info->nRefs;    else        p = 0, info = 0;}template <class T>    template <class T_>        SdPtr<T> &SdPtr<T>::operator =(const SdPtr<T_> &a){    if (p!=a.p)    {        DestroyRef();        if (a)            p = a.p, info = a.info, ++info->nRefs;        else            p = 0, info = 0;    }    return *this;    }template <class T>    void SdPtr<T>::Set(T *pSelfDestructive){    if (pSelfDestructive)    {        PtrInfo *info_ = CreateInfo(pSelfDestructive);        DestroyRef();        p = pSelfDestructive;        info = info_;        p->SelfDestructive::info = info;    }    else        DestroyRef(), p=0;}template <class T>    typename SdPtr<T>::PtrInfo *SdPtr<T>::CreateInfo(T *p){    if (p)        try            { return new PtrInfo(p); }        catch (...)            { delete p; throw; }    return 0;}template <class T>    void SdPtr<T>::DestroyRef(){    if (p && !--info->nRefs)    {        if (info->p)            delete p;        delete info;    }}
// Example.cpp#include <iostream>#include "SelfDestructive.h"class X : virtual public SelfDestructive{public:    X() { std::cout << "X()" << std::endl; }    ~X() { std::cout << "~X()" << std::endl; }    void f() { std::cout << "X::f()" << std::endl; }    void Delete()    {        std::cout << "Delete X?" << std::endl;        int n = 0;        std::cin >> n;        if (n)            Destroy();    }};int main(){    SdPtr<X> ptr(new X);    std::cout << (ptr!=0) << std::endl;    ptr->f();    ptr->Delete();    std::cout << (ptr!=0) << std::endl;}
Объекты создаются в динамической памяти через new и сразу же отдаются во владение SdPtr. Если объект сам себя уничтожит, то все указывавшие на него указатели SdPtr будут об этом знать, и пользователь имеет возможность это проверить.