Question

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.

Was it helpful?

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.)

OTHER TIPS

Thanks for your reply.

You were right.

The correct code is now as follows:

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 std::enable_shared_from_this<Foo> 
{
public:
    Foo() { printf( "foo()\n"); }
    ~Foo() { printf( "~foo()\n"); }
public:
    void doSomething() { DoSomething::doSomething(this->shared_from_this()); }
    void doSomethingElse() { DoSomething::doSomethingElse(this->shared_from_this()); }
};

int _tmain(int argc, _TCHAR* argv[])
{
    {
        auto pFoo = std::make_shared<Foo>();
        pFoo->doSomething();
        pFoo->doSomethingElse();
    }
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top