插入无序地图调用构造函数

时间:2015-04-28 19:09:49

标签: c++ c++11 containers destructor rvalue

为了避免重复元素,我正在构建一个包含元素并提供对它们的访问的类。

我的元素(DynLibrary)是可移动但不可复制的

class DynLibrary
{
    public:
        DynLibrary() : _handle(nullptr) {}
        DynLibrary(const std::string& path) { DynLibrary::open(path); }
        DynLibrary(const DynLibrary&) = delete;
        DynLibrary(DynLibrary&&) = default;
        ~DynLibrary() { DynLibrary::close(); }
    ...
}

这些对象在unordered_map中分配,哪个键是生成它们的路径。 我这样分配它们

class DynAllocator
{
    public:
        DynLibrary& library(const std::string& f)
        {
            if (_handles.find(f) == _handles.end())
            {
                std::cout << "@Emplace" << std::endl;
                _handles.emplace(f, DynLibrary(f));
            }
            std::cout << "@Return" << std::endl;
            return _handles.at(f);
        }
    private:
        std::unordered_map<std::string, DynLibrary> _handles;
};

但是,在调用DynAllocator::library时,我得到以下输出:

@Emplace
close 0x1dfd1e0 // DynLibrary destructor
@Return

这意味着插入的对象以某种方式被复制,副本的析构函数使我的对象无效(使用我的处理程序调用{​​{1}})

  • dlclose好吗?
  • 是我可移动但不可复制的方法吗?
  • 如果我的DynLibrary没有副本,如何插入DynLibrary的实例?

请注意我知道如何使用指针/智能指针(unordered_map),但我想不惜一切代价避免使用它们!

1 个答案:

答案 0 :(得分:3)

  

这意味着插入的对象以某种方式被复制,副本的析构函数使我的对象无效

不,那不是那个意思。 DynLibrary有一个delete d复制构造函数,因此如果通过重载解析以某种方式选择了该构造函数,则代码将无法编译。

_handles.emplace(f, DynLibrary(f));

上面的行是你正在创建一个临时的DynLibrary对象,然后将移动构造创建到unordered_map。如果您希望避免此移动构造,请改用std::piecewise_construct

_handles.emplace(std::piecewise_construct,
                 std::forward_as_tuple(f),
                 std::forward_as_tuple(f));

现在,您正在DynLibrary内直接构建unordered_map对象,并绕过临时创建。

作为T.C. comments,在这种情况下,不需要分段构造构造函数,因为DynLibrary具有非explicit转换构造函数。使用

可以达到与上述相同的效果
_handles.emplace(f, f);