Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ use Smart Pointers with changing pointer values

Tags:

Consider a C library that defines functions for creating, destroying and working with a custom structure

struct Foo; void foo_action(Foo*); Foo* foo_create(); void foo_free(Foo*); 

Currently, I used the library in my C++ project as follows

Foo* myfoo = foo_create(); foo_action(myfoo); foo_free(myfoo); 

I understand why smart pointers are important and want to migrate my code to use them. That's how the code looks now.

#include <memory> #include <functional> typedef std::unique_ptr<Foo, std::function<void(Foo*)>> FooPtr; // ... FooPtr myfoo2(foo_create(), foo_free); foo_action(myfoo2.get()); 

It seems to work, but the myfoo2.get() invocation seems hacky. Am I using it as intended?

There's another part of the library which creates and works with some kind of list structure. The api looks like

struct Bar; Bar* bar_append(Bar*, int); void bar_free_recursive(Bar*); 

and is used as

// using NULL as current Bar* creates the initial structure Bar* bar = bar_append(NULL, 1); // each invocation leads to another 'head' structure bar = bar_append(bar, 42); bar = bar_append(bar, 123); 

As the pointer (the address pointed to) changes with each bar_append invocation, how would I introduce smart pointers here, so that bar_free_recursive is invoked on the current pointer value when the pointer instance is freed?

like image 847
muffel Avatar asked Oct 30 '17 12:10

muffel


People also ask

Why should you use smart pointers instead of regular pointers?

Smart pointers try to prevent memory leaks by making the resource deallocation automatic: when the pointer to an object (or the last in a series of pointers) is destroyed, for example because it goes out of scope, the pointed object is destroyed too.

How many times can a unique pointer be copied to create another smart pointer?

Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.

Why auto_ptr is deprecated?

Single most important reason as to why auto_ptr was deprecated in favor of smart-pointer is assignment-semantics If it wasn't for that reason, they would have added all the new goodies of move semantics to the auto_ptr instead of deprecating it.

How do you assign a value to a shared pointer?

You cannot assign the value of a pointer directly to a shared_ptr object. You may either use make_shared or member reset instead.


1 Answers

but the myfoo2.get() invocation seems hacky. Am I using it as intended?

It is not hacky, you use it as intended.

I would go one step further and wrap the whole in a class:

struct Foo; void foo_action(Foo*); Foo* foo_create(); void foo_free(Foo*);  class FooWrapper { public:     FooWrapper() : mFoo(foo_create()) {}      void action() { foo_action(mFoo.get()); } private:     struct FooDeleter     {         void operator()(Foo* foo) const { foo_free(foo); }     };      std::unique_ptr<Foo, FooDeleter> mFoo; }; 

In the same way:

struct Bar; Bar* bar_append(Bar*, int); void bar_free_recursive(Bar*);  class BarWrapper { public:     explicit BarWrapper(int n) : mBar(bar_append(nullptr, n)) {}      void append(int n) { mBar.reset(bar_append(mBar.release(), n)); }  private:     struct BarDeleter     {         void operator()(Bar* bar) const { bar_free_recursive(bar); }     };      std::unique_ptr<Bar, BarDeleter> mBar; }; 
like image 146
Jarod42 Avatar answered Oct 04 '22 12:10

Jarod42