为了避免元素重复,我正在构建一个包含元素并提供对它们的访问的类。
我的元素 (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
这意味着插入的对象已以某种方式被复制,并且拷贝的析构函数只是使我的对象无效(使用我的处理程序调用dlclose
)
- 我的
DynLibrary
可移动但不可复制的方法可以吗? - 如果我的
unordered_map
没有拷贝,如何插入DynLibrary
实例?
请注意,我知道如何使用指针/智能指针(std::unique_ptr
)来做到这一点,但我想不惜一切代价避免它们!
最佳答案
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 复制构造函数,因此如果通过重载解析以某种方式选择该构造函数,则代码将无法编译。
_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));
现在,您可以直接在 unordered_map
中构造 DynLibrary
对象,并绕过临时创建。
作为 T.C. comments ,在这种情况下分段构造函数不是必需的,因为 DynLibrary 有一个非显式转换构造函数。您可以通过以下方式达到与上面相同的效果
_handles.emplace(f, f);
关于c++ - 插入无序映射调用构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29927882/