简体   繁体   中英

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.

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

在此处输入图像描述

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.

I'd suggest using references/raw pointers depending if you want to pass nullptr or not. Why? It is a good guideline to pass as little as required - if you do not need increasing reference count or do anything specific with shared_ptr passing it is not required and may be misleading.

About your questions - both are rather safe IF the wrapped API can handle nullptr . If not (and this is suggested by your assert ), references will be safer.

The reference counting will work same way for all of the approaches since you pass by reference. Should you passed by value it would increase reference count for the call of function.

All in all, my suggested solution:

// wrapper

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

    ThirdParty_DoStuff(&pInObj, &out_pOutObj);
}

// client code

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

MyWrapper(*inObj, *outObj);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM