如何正确处理带有移动构造函数的shared_ptr映射?

时间:2012-08-28 15:22:27

标签: c++ map shared-ptr

考虑我有一个容器std::map<int, std::shared_ptr<MyClass>>,我希望将其填入外部函数并避免处理其内容。所以我有

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.

}

如果我使用传统的复制构造函数,一切都按预期工作。

2 个答案:

答案 0 :(得分:6)

太复杂了。为什么不这样说:

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

    // ...
}

如果绝对必须使用辅助函数,则必须返回一个对象,而不是悬空引用。像这样:

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

很难放纵任何比这更多的行人,而是一个最终的,永远不会被用于家庭的版本:

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;
}

答案 1 :(得分:0)

问题是您要从f()返回引用。右值引用仍然是一个引用,就像你永远不会从函数中返回对本地的引用一样,你也不能使用右值引用。

好消息是你没必要。感谢return value optimization,您只需从Container返回f()即可,它将完全符合您的要求。