Search code examples
c++classshared-ptrsmart-pointersweak-ptr

c++: std::tr1::shared_ptr from this


I have the following code:

#include <memory>

class Foo;
typedef std::tr1::shared_ptr<Foo> pFoo_t;

class DoSomething
{
public:
    static void doSomething( pFoo_t p) { printf( "doing something...\n"); }
    static void doSomethingElse( pFoo_t p) { printf( "doing something else...\n"); }
};

class Foo
{
public:
    Foo() { printf( "foo()\n"); }
    ~Foo() { printf( "~foo()\n"); }
public:
    void doSomething() { DoSomething::doSomething(pFoo_t(this)); }
    void doSomethingElse() { DoSomething::doSomethingElse(pFoo_t(this)); }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo foo;
    foo.doSomething();
    foo.doSomethingElse();

    return 0;
}

I start this sample and I get next assert: _BLOCK_TYPE_IS_VALID(pHead->nBloakUse).

How can I avoid this?

I used the following code for resolve this problem:

class Foo;
typedef std::tr1::shared_ptr<Foo> pFoo_t;

class DoSomething
{
public:
    static void doSomething( pFoo_t p) { printf( "doing something...\n"); }
    static void doSomethingElse( pFoo_t p) { printf( "doing something else...\n"); }
};

class Foo
{
public:
    void Init(pFoo_t _pFoo) { m_pFoo = _pFoo; }
    Foo() { printf( "foo()\n"); }
    ~Foo() { printf( "~foo()\n"); }
public:
    void doSomething() { DoSomething::doSomething(m_pFoo.lock()); }
    void doSomethingElse() { DoSomething::doSomethingElse(m_pFoo.lock()); }
private:
    std::tr1::weak_ptr<Foo> m_pFoo;
};

int _tmain(int argc, _TCHAR* argv[])
{
    {
        Foo * foo = new Foo();
        pFoo_t pFoo(foo);
        foo->Init(pFoo);
        foo->doSomething();
        foo->doSomethingElse();
    }
    return 0;
}

But I think there is a better solution.


Solution

  • Don't implement this manually. Make your class inherit from std::enable_shared_from_this and use std::shared_from_this() to get a shared pointer.

    Moreover, you should allocate your object right into a shared pointer:

    pFoo_t pFoo = std::make_shared<Foo>();  // good
    pFoo_t pFoo(new Foo());                 // legacy
    

    (By the way, you either include <memory> for this, or you use the TR1 versions of all this (then there's no make_shared) and include <tr1/memory>. I know that MSVC lets you get away with lots of sloppiness, but for the sake of portability you should pick one or the other.)