Chris
Chris

Reputation: 31206

C++: pass shared ptr by reference without breaking the sharing?

Suppose I use smart pointers? Ok, great:

shared_ptr<whatever>(new whatever());

Instantly, I want to do the following rather than tangle with C++'s single-return item policy and the semantic mess therein:

void do_something(whatever *& A, whatever *& B){
  auto Aptr = shared_ptr<whatever>(new whatever());
  A = Aptr.get();

  auto Bptr = shared_ptr<whatever>(new whatever());
  B = Bptr.get();
}

However, the shared_ptr mechanic deletes the objects as they are passed out of the function by reference so that, while the pointers in my calling code,

whatever *A,*B;
do_something(A,B);

Get set to the appropriate address by reference, the data has been obliterated.


All of this is to avoid the snarl of typing and documentation at the return type, as it is very natural to accumulate arguments in a list...but every additional item in the return tray splits context hinting across documentation.

Accessing values initialized by reference is altogether a desirable mechanic.


Also, I would like to add that I have gotten this mechanic to work, just so long as I own the pointers with the shared pointer in the calling scope.

However, this is a recursive repeat of the same problem: I would like to automatically manage the pointers inside the function and return them by reference to exterior variables, so that there is a look and feel of normal C pointers, but no mallocs or frees at the outer scope -- I just declare the pointers and pass them by reference.

Instead, I have 2 lines for every pointer: the declaration, the function that constructs their innards, and a shared ptr that owns them *after the function call. Just another version of the malloc-free mechanic.

Ideally, there is a way to drop that second line where I own the ptr with a shared pointer, or (if that isn't possible), a way to initialize a shared pointer inside a function after declaring the pointer shared on the outside. Note that the goal here is:

void func(double * a, int * b, T * c);

double *a; 
int *b; 
T *c;
func(a,b,c); 
// no headaches whatsoever at this scope.

// versus

double *a; 
int *b; 
T *c;
func(a,b,c);
shared_ptr<double> asp(a);
shared_ptr<int> bsp(b);
shared_ptr<T> csp(c,[](T*_){/*special T deletion process*/;};

// versus

double *a; 
int *b; 
T *c;
func(a,b,c);

/* solve the universe */

free(a);
free(b);
delete(T);

Upvotes: 0

Views: 166

Answers (3)

Massimo Castrioto
Massimo Castrioto

Reputation: 25

I have a bad answer, but it sould do what you want.

void do_something( whatever *& A, whatever *& B ) {
    static std::shared_ptr<whatever> ptr_a;
    static std::shared_ptr<whatever> ptr_b;
    ptr_a.reset( new whatever );
    ptr_b.reset( new whatever );
    A = ptr_a.get();
    B = ptr_b.get();
}

It will free your memory the next time you call the function, or when the program ends, so depending on how much memory you need...

I thought I'd write it even if it's a bad answer.

A different answer that is not so bad would be having a class like this:

class Shallocator
{
public:
    Shallocator( whatever *& A, whatever *& B ) {
        ptr_a.reset( new whatever );
        ptr_b.reset( new whatever );
        A = ptr_a.get();
        B = ptr_b.get();
    }
private:
    std::shared_ptr<whatever> ptr_a;
    std::shared_ptr<whatever> ptr_b;
};

then in the function you go:

whatever * A, * B;
Shallocator { A, B };

// no headaches

Memory will be freed when the lifetime of the Shallocator ends.

Upvotes: 0

Chris Dodd
Chris Dodd

Reputation: 126203

Just use shared pointers uniformly everywhere:

void do_something(std::shared_ptr<whatever> &A, std::shared_ptr<whatever> &B) {
           :

Upvotes: 1

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136256

May be your problem can be solved by a structure with a constructor or two:

struct NoNeadachesWhatsoever {
    shared_ptr<double> asp;
    shared_ptr<int> bsp;
    shared_ptr<T> csp;

    NoNeadachesWhatsoever() {
        // initialize members.
    }
};

// ...

NoNeadachesWhatsoever no_headaches_whatsoever;

Upvotes: 2

Related Questions