为了避免重复元素,我正在构建一个包含元素并提供对它们的访问的类。
我的元素(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
),但我想不惜一切代价避免使用它们!
答案 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);