插入无序的地图调用构造函数 [英] Insert in unordered map calls constructor
问题描述
为了避免元素重复,我正在构建一个包含元素并为其提供访问权限的类.
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 myunordered_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 delete
d 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屋!