Home > Mobile >  What's the purpose of using pointer to std::shared_ptr in C library Gandiva
What's the purpose of using pointer to std::shared_ptr in C library Gandiva

Time:01-12

I'm learning the Gandiva module in Apache Arrow. I found that many APIs require parameters in the form of std::shared_ptr<T>*, eg here is an typical API:

static inline Status Make(SchemaPtr schema, ConditionPtr condition, std::shared_ptr<Filter> *filter)

I don't understand why it uses a pointer to a shared_ptr instead of a simple shared_ptr. To my understanding, a raw pointer should be avoided in C as much as possible, and shared_ptr is designed as an alternative to using raw pointers.

CodePudding user response:

This is a way for the API to "return" a shared_ptr to you. I have not used this library, but here is an example of what an API like this might do:

static inline Status Make(SchemaPtr schema, ConditionPtr condition, std::shared_ptr<Filter> *filter) {
   // ...more stuff here...

   // Assign a new instance of shared_ptr to the variable that the caller passed in
   *filter = std::make_shared<Filter>(...);
   return Status{"ok"};

}

This is often called an "out" parameter and it is documented as such in the API you linked.

There are alternatives.

  1. The function can use references, but those can disguise the fact that out parameters are being used. Make(a, b, c) looks like passing in three normal parameters but Make(a, b, &c) can tip someone off that out parameters are being used. This is one reason it is common to prefer pointers over references for out parameters.
  2. The function could return a std::tuple<Status, std::shared_ptr<Filter>> instead.

Sometimes when using the raw pointer argument, the library may check if the pointer is null and not assign anything to it in that case. That would make the out parameter optional, which neither of these alternatives can handle. (here is an example of an API using the optional out parameter with a raw pointer: https://doc.qt.io/qt-6/qstring.html#toInt)

The general rule in modern c is to avoid using raw pointers when you want to control ownership. This example does not take ownership of the passed in pointer and so does not break that rule.

Some people conform to a stricter rule where they try to avoid pointers everywhere, but that is less popular.

CodePudding user response:

This is their code style convention for output parameters.

filter[out] the returned filter object

Usage

std::shared_ptr<Filter> filter;
Filter::Make(..., &filter);

I would use

Status Make(..., std::shared_ptr<Filter> &filter);

std::shared_ptr<Filter> filter;
Filter::Make(..., filter);

Perhaps seeing the usage &filter they know filter is an output argument w/o looking at the function declaration.

Apache Arrow Development Guidelines - Code Style, Linting, and CI

  • We prefer pointers for output and input/output parameters (the style guide recommends mutable references in some cases).
  • Related