Search code examples
c++performancepointersmemory

Whether to pass shared pointer or raw pointer to a function


Situation

Some third-party API I use works with raw pointers, but I have smart pointers all over my client code.

Problem

When I want to write a wrapper function around the API, I face a problem: Whether to pass shared pointers or their raw pointers underneath as arguments.

Like this:

The smart pointer version


// my wrapper

void MyWrapper(const std::shared_ptr<MyClassA>& pInObj, std::shared_ptr<MyClassB>& out_pOutObj) {

    ThirdParty_DoStuff(pInObj.get(), out_pOutObj.get());
}

// my client code

auto inObj = std::make_shared<MyClassA>();
auto outObj = std::make_shared<MyClassB>();

MyWrapper(inObj, outObj);

The raw pointer version


// wrapper

void MyWrapper(MyClassA* pInObj, MyClassB* out_pOutObj) {

    assert(pInObj && out_pOutObj);
    ThirdParty_DoStuff(pInObj, out_pOutObj);
}

// client code

auto inObj = std::make_shared<MyClassA>();
auto outObj = std::make_shared<MyClassB>();

MyWrapper(inObj.get(), outObj.get());

Question

  • Which is the better approach in terms of performance and memory safety?
  • Will the reference counting work slightly differently between both approaches?

I think that the second version is more reusable if one day the function must work with other kinds of memory management.


Solution

  • I would suggest the following approach to looking at code something like this:

    enter image description here

    There are some other options like weak_ptr, but for this it is probably not worth looking at.

    So for your example, we can see that ThirdParty_DoStuff does not take ownership, so we won't either, so you can choose between a reference and a pointer depending on if the argument is mandatory or not respectively.

    EDIT: As of c++17, you have the option of using optional This can also now cover the case where you have an optional output.