【问题标题】:what to use in place of std::map::emplace?用什么代替 std::map::emplace?
【发布时间】:2012-12-09 04:52:20
【问题描述】:

对于像std::map< std::string, std::unique_ptr< Foo >> 这样的容器,看起来emplace() 在 gcc 4.7.2 中还没有在 stdc++ 中实现。

不幸的是,我不能直接按值存储 Foo,因为它是一个抽象超类。

作为一个简单但低效的占位符,我一直在使用 std::map< std::string, Foo* >std::vector< std::unique_ptr< Foo >> 进行垃圾收集。

您是否有一个临时解决方案,在 emplace() 可用后更高效且更容易替换?

【问题讨论】:

    标签: c++ c++11 std


    【解决方案1】:

    您需要emplace() 做什么?把它搬进去:

    #include <iostream>
    #include <map>
    #include <memory>
    #include <string>
    
    struct Foo
    {
        virtual ~Foo() = default;
    
        virtual std::string name() const = 0;
    };
    
    struct Bar : Foo
    {
        std::string name() const { return "Bar"; }
    };
    
    int main()
    {
        std::map<std::string, std::unique_ptr<Foo>> m;
    
        std::unique_ptr<Foo> p(new Bar());
        m.insert(std::make_pair("a", std::move(p)));
    
        std::cout << m["a"]->name() << std::endl;
    }
    

    事实上,you should not use emplace with unique_ptr's

    正如我在评论中所述,我现在认为在用户代码中使用 new 是一个错误。它应该替换为make_unique,这样你就知道你的资源不可能泄漏:

    // will be in std:: someday
    template <typename T, typename... Args>
    std::unique_ptr<T> make_unique(Args&&... args)
    {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }
    
    int main()
    {
        std::map<std::string, std::unique_ptr<Foo>> m;
    
        m.insert(std::make_pair("a", make_unique<Bar>()));
    
        std::cout << m["a"]->name() << std::endl;
    }
    

    【讨论】:

    • +1 以获得可用代码的良好答案。避免在用户代码中使用new 是一个勇敢的原因。但是,假设我不需要构造一个新的 Bar 实例,而是需要在地图中插入一个 foo-&gt;clone(),因为我不知道我有什么样的 Foo?你如何让Foo* Bar::clone() 避免调用new?或者这样可以吗,因为它不会被视为客户端代码?
    • 巧合的是,我今天刚刚处理了这个问题。让你的克隆函数返回std::unique_ptr&lt;Foo&gt;
    • 我知道这有点老了,但是如果 foo->clone() 的用户想要一个 shared_ptr 怎么办?
    • @DaliborFrivaldsky:您可以从 unique_ptr 构造一个 shared_ptr。
    【解决方案2】:

    作为一种解决方法,您可以使用 boost 容器,即使在 C++ 03 编译器下也支持大多数 C++ 11 功能,并且具有与 std 容器相同的布局,然后当您拥有 std 的功能时,您可以切换名称空间!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多