Search code examples
c++boostsmart-pointersshared-ptr

shared_ptr and references in C++


References in C++ are a conveneint construct that allow us to simplify the following C code:

f(object *p){
  //do something
}

int main(){
  object* p = (object*) calloc(sizeof(object));
  f(p);
}

to

f(object& o){
  //do something
}

int main(){
  object o = object();
  f(o);
}

Shared pointers are another convenience in C++ that simplify memory management. However, I am not sure how to pass a shared_ptr to a function like f(object& o) which accepts arguments by reference?

f(object& o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(*p);
}

Will the shared pointer be incremented when its object is passed by reference to a function?


Solution

  • Take a shared_ptr by value, and the reference count will increase. This is easier when you typedef it:

    typedef boost:shared_ptr<object> object_ptr;
    
    void foo(object_ptr obj)
    {
        obj->/* stuff*/;
        obj.reset(); //only resets this local copy, that means:
                     // reduce reference count (back to 1), and
                     // set obj to point at null.
    }
    
    int main(void)
    {
        object_ptr obj(new object());
        foo(obj);
    }
    

    Keep in mind references are aliases. When you pass by reference, you're not passing pointers, copies, etc..., you're aliasing another object. (In reality they are implemented as pointers):

    typedef boost:shared_ptr<object> object_ptr;
    
    void foo(object_ptr& obj)
    {
        obj.reset(); // the references was never increased, since a copy has not
                     // been made, this *is* obj in main. so the reference 
                     // goes to 0, and obj is deleted
    }
    
    int main(void)
    {
        object_ptr obj(new object);
        foo(obj); // after this, obj has been reset!
    }
    

    Always remember to be const correct, to prevent errors:

    typedef boost:shared_ptr<object> object_ptr;
    
    void foo(const object_ptr& obj)
    {
        obj.reset(); // cannot do! 
    }
    
    int main(void)
    {
        object_ptr obj(new object);
        foo(obj);
    }
    

    I think you should prefer to pass smart pointers as references when possible, to avoid extraneous increments and decrements (and copies and whatnot).