How to handle shared_ptr map with move constructor correctly?

I have a container std::map<int, std::shared_ptr<MyClass>> , and I want to fill it with an external function and avoid matching its contents. So i

 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 the regular copy constructor, everything works as expected.

+4
source share
2 answers

This is too complicated. Why not just say the following:

 int main() { Container baz { { 0, std::make_shared<MyClass>() } }; // ... } 

If you absolutely must go with an auxiliary function, you need to return the object, and not dangle the link. Something like that:

 Container f() { return Container { { 0, std::make_shared<MyClass>() } }; } 

It's hard to indulge anything more pedestrian than this, but one final, never-used 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; } 
+6
source

The problem is that you are returning a link from your f() . The rvalue link is still a link, and just like you will never return a link to a local one from a function that you cannot do with rvalue links.

The good news is that you do not need to. By optimizing the return value, you can simply return the Container from f() , and it will do exactly what you are looking for.

0
source

All Articles