Jump to content
  • Advertisement
Sign in to follow this  
rpiller

C++ Outside the box smart pointers

This topic is 2102 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Don't yell at me because this seems to get people upset smile.png, but I hate wrapping pointers up in a templated class to make it smart. I hate making parameters that take smart pointer templated arguments, so I took these hates and started thinking about how would I remove them. This isn't for anything production or anything, just me trying to remove dislikes to see if I can do it in C++.

 

I set out to make smart pointers that look and feel just like normal pointers. This is meant to keep a ref count and only actually free the object when that ref count reaches 0.

 

Below is my result which seems to work, but I have 2 issues that prevent this from working/easier. When one pointer is assigned to another I would need to know this so that I can automatically call AddRef() instead of right now I explicitly call it. When inside the delete operator, when the ref count reaches 0 and after I explicitly call the destructor I need to actually free the memory of the object itself.

 

I know this is outside the norm but if anyone can think of a better way to handle my 2 remaining issues I'd be interested (without templates).

 

[EDIT]

Calling free() on the void* passed into the delete operator seems to have actually removed the object itself so I think I got that issue solved. I just need an automated way to increase the reference when you assign one pointer to another.

class Test
{
private:
    int a;
public:
    Test()
    {
        a = 5;
    }
};
 
class Object
{
private:
    int refCount;
    Test* test;
public:
    Object()
    {
        refCount = 1;
        test = new Test();
    }
 
    ~Object()
    {
        if(refCount > 0)
            return;
 
        delete test;
    }
 
 
    void AddRef()
    {
        refCount++;
    }
 
    void Release()
    {
        refCount--;
    }
 
    int GetRefCount()
    {
        return refCount;
    }
 
    void operator delete( void* obj )
    {
        Object* o = (Object*)obj;
 
        o->Release();
 
        if(o->GetRefCount() == 0)
        {
            o->~Object();
 
            free(obj);
        }
     }
};
 
 
class Team
{
private:
    Object* obj;
public:
    Team(Object* o)
    {
        // need to know this is happening so we can automatically cal AddRef()
        obj = o;
 
        obj->AddRef();
    }
    void Update()
    {
        delete obj;
        obj = 0;
    }
};
 
 
int main()
{
    // a is a smart pointer so when Team deletes it, it knows another reference exists so it doesn't actually remove the object from memory
    Object* a = new Object();
    Team team(a);
 
    // this "deletes" a
    team.Update();
 
    int count = a->GetRefCount();
 
    // once the ref count is set to 0 we do actually want to remove it from memory, but how?
    delete a;
 
    count = a->GetRefCount();
 
    return 0;
}
Edited by rpiller

Share this post


Link to post
Share on other sites
Advertisement

What part of smart pointers are an annoyance to you? If it's the extra typing, just type-def it.

class MyObject
{
    public:
    typedef std::shared_ptr<MyObject> sPtr;
};

void doSomething(MyObject::sPtr &myPtr);

Share this post


Link to post
Share on other sites

Explicitly calling a destructor on an object not created with placement new is bad juju. You're basically asking for double-destruction to occur on your object.

 

 

Can you elaborate on this? 'placement new' ? How would the double destruction occur given the check in the destructor checking the ref count? Is that generally the blanket answer for anytime someone is calling a destructor manually?

 

Using typedef is a valid solution for C++ but I'm just curious if this can be done without templates so a pointer looks and feels exactly like a normal pointer in every way without modification on the outside.

 

 


Aside from globally overriding operator= for pointer types,

 

 

My understanding is that the operator= can't be overloaded for pointers sad.png

 

 

 

I find it interesting the code I have above seems to work (surprised actually :) ), it's just that I need to manually call AddRef() when assigning a pointer to another pointer which doesn't make it automatic.

Edited by rpiller

Share this post


Link to post
Share on other sites

I guess a similar (maybe less offensive? smile.png ) way would be to do something like:

void Dispose()
{
    refCount--;
 
    if(this->GetRefCount() == 0)
        delete this;
}

Given http://www.parashift.com/c++-faq-lite/delete-this.html

 

 

Still requires manually calling it sad.png. Sucks that we have to use scope of another object to get info about some actions going on (copy ctor to AddRef(), destructor to Release()). That's basically what's happening with smart pointers right. We need to know when certain actions happen and scoping rules provide callbacks of sort to tell us this. Almost makes it seem like an unintentional usage of scope (ie. hack).

Edited by rpiller

Share this post


Link to post
Share on other sites

Yeah, it seems that way. I'd take inheritance if that worked but doesn't seem like it does as the needed events just aren't available. It's interesting that it looks like it's almost there.

Edited by rpiller

Share this post


Link to post
Share on other sites

Do you plan on adding thread safety to your pointer wrapper? I believe shared_ptr has this built in as part of its smart-ness... (obviously not on the object itself though).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!