Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I store a function's output parameter into a unique_ptr?

I have the following code:

class Thing
{};

void fnc(Thing** out)
{
    *out = new Thing();
};

Where fnc returns a new instance of Thing via output parameter. Normally I'd use it as follows:

int main()
{
    Thing* thing;
    fnc(&thing);  
}

Can I put the returned object in a std::unique_ptr instead?

int main()
{
    std::unique_ptr<Thing> uniqueThing;
    fnc(???);
}
like image 656
Ignorant Avatar asked Jul 22 '17 09:07

Ignorant


3 Answers

To extend your code sample, it (i.e. pass-by-pointer) would be

void fnc(std::unique_ptr<Thing>* out)
{
    out->reset(new Thing());
};

int main()
{
    std::unique_ptr<Thing> uniqueThing;
    fnc(&uniqueThing);  
}

or use pass-by-reference:

void fnc(std::unique_ptr<Thing>& out)
{
    out.reset(new Thing());
};

int main()
{
    std::unique_ptr<Thing> uniqueThing;
    fnc(uniqueThing);  
}

But I think return the pointer by return value would be more clear:

std::unique_ptr<Thing> fnc()
{
    return std::unique_ptr<Thing>(new Thing);
    // or
    // return std::make_unique<Thing>();
};

int main()
{
    auto uniqueThing = fnc();
}
like image 119
songyuanyao Avatar answered Nov 14 '22 21:11

songyuanyao


You should store the raw pointer in the unique_ptr so that the unique_ptr takes ownership:

Thing* thing;
fnc(&thing);
std::unique_ptr<Thing> thing_unique (thing);
like image 21
Hatted Rooster Avatar answered Nov 14 '22 23:11

Hatted Rooster


You can't do that directly. You'll have to use a temporary variable:

Thing* thing{};
fnc(&thing);

uniqueThing.reset(*thing);

Or even better, because fnc doesn't a return an error code or something else, you can just return the new pointer which let's write initialize uniqueThing directly:

std::unique_ptr<Thing> uniqueThing{fnc()};
like image 30
Rakete1111 Avatar answered Nov 14 '22 22:11

Rakete1111