Reputation: 1000
Consider I have a container std::map<int, std::shared_ptr<MyClass>>
and I want to fill it in external function and avoid coping of its contents. So I have
typedef Container std::map<int, std::shared_ptr<MyClass>>
Container&& f(){
Container bar;
auto foo = std::shared_ptr<MyClass>(new MyClass());
bar.insert(std::make_pair(0,foo));
std::cout<<bar.at(1)->print_smth<<'\n'; //This works
return std::move(bar);
}
int main(){
Container baz(f());
std::cout<<bar.at(1)->print_smth<<'\n'; //This doesn't
// Container baz has element 1, but shared_ptr is invalidated, because it has 0 references.
}
If I use conventional copy constructor everything works as expected.
Upvotes: 4
Views: 6124
Reputation: 5135
The problem is that you are returning a reference from your f()
. An rvalue reference is still a reference and just like you would never return a reference to a local from a function you can't do that with rvalue references either.
The good news is that you don't have to. Thanks to the return value optimization you can simply return a Container
from f()
and it will do exactly what you are looking for.
Upvotes: 0
Reputation: 476990
This is far too complicated. Why not just say this:
int main()
{
Container baz { { 0, std::make_shared<MyClass>() } };
// ...
}
If you absolutely must go with the helper function, you have to return an object, not a dangling reference. Something like this:
Container f()
{
return Container { { 0, std::make_shared<MyClass>() } };
}
It's hard to indulge anything more pedestrian than this, but one final, never-to-be-used-at-home version:
Container f()
{
Container bar;
auto p = std::make_shared<MyClass>;
bar[0] = p; // Method #1
// ---- ALTERNATIVELY ---
bar.insert(std::make_pair(0, p)); // Method #2
// ---- ALTERNATIVELY ---
bar.emplace(0, p); // Method #3
return bar;
}
Upvotes: 6