插入无序的地图调用构造函数 [英] Insert in unordered map calls constructor

查看:81
本文介绍了插入无序的地图调用构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了避免元素重复,我正在构建一个包含元素并为其提供访问权限的类.

In order to avoid duplication of elements, I'm building a class that holds elements and provide an acces to them.

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

My elements (DynLibrary) are movable but not copyable

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 中分配,该键是生成它们的路径.我是这样分配他们的

Those object are allocated in an unordered_map which key is the path that generated them. I'm allocation them that way

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 时,我得到以下输出:

However when calling DynAllocator::library I get the following output:

@Emplace
close 0x1dfd1e0 // DynLibrary destructor
@Return

这意味着插入的对象已经以某种方式被复制,并且复制的析构函数使我的对象无效(使用处理程序调用 dlclose )

Which means that the object which is inserted has somehow been copied and the destructor of the copy just invalidated my object (calling dlclose with my handler)

  • 我的 DynLibrary 可移动但不可复制的方法好吗?
  • 如果我的 unordered_map 没有副本,如何插入 DynLibrary 的实例?
  • Is my movable but not copyable approach of DynLibrary ok ?
  • How can I insert an instance of DynLibrary if my unordered_map without copy ?

请注意,我知道如何使用指针/智能指针( std :: unique_ptr )来做到这一点,但我想不惜一切代价避免使用它们!

Please note that I know how to do that using pointers / smart pointers (std::unique_ptr) but that i'd like to avoid them at all cost !

推荐答案

这意味着插入的对象已经以某种方式被复制,而复制的析构函数只是使我的对象无效

Which means that the object which is inserted has somehow been copied and the destructor of the copy just invalidated my object

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

No, that's not what that means. DynLibrary has a deleted copy constructor, so the code would not compile if that constructor were somehow chosen through overload resolution.

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

上面一行发生的事情是您正在创建一个临时的 DynLibrary 对象,然后将其移动构造 unordered_map 中.如果您希望避免这种移动结构,请使用 std :: piecewise_construct .

What's happening on the line above is you're creating a temporary DynLibrary object which is then move constructed into the unordered_map. If you wish to avoid this move construction, use std::piecewise_construct instead.

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

现在,您将直接在 unordered_map 中构造 DynLibrary 对象,并绕过临时对象的创建.

Now you're directly constructing the DynLibrary object within the unordered_map and bypassing creation of the temporary.

作为T.C.评论,分段构造构造函数不是在这种情况下是必需的,因为 DynLibrary 具有非 explicit 转换构造函数.您可以使用

As T.C. comments, the piecewise construction constructor is not necessary in this case because DynLibrary has a non-explicit converting constructor. You can achieve the same effect as above with

_handles.emplace(f, f);

这篇关于插入无序的地图调用构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆