C++ 插入无序映射调用构造函数
为了避免元素的重复,我正在构建一个类来保存元素并提供对它们的访问 我的元素(C++ 插入无序映射调用构造函数,c++,c++11,containers,destructor,rvalue,C++,C++11,Containers,Destructor,Rvalue,为了避免元素的重复,我正在构建一个类来保存元素并提供对它们的访问 我的元素(DynLibrary)是可移动的,但不可复制 class DynLibrary { public: DynLibrary() : _handle(nullptr) {} DynLibrary(const std::string& path) { DynLibrary::open(path); } DynLibrary(const DynLibrary&
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(); }
...
}
这些对象在一个无序的
映射中分配,该键是生成它们的路径。
我是这样分配的
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;
};
这意味着插入的对象已被复制,而副本的析构函数刚刚使我的对象无效(使用我的处理程序调用dlclose
)
- 我的
可移动但不可复制的方法可以吗DynLibrary
- 如果我的
没有副本,如何插入无序映射
动态库的实例李>
std::unique_ptr
)实现这一点,但我希望不惜一切代价避免它们
这意味着插入的对象已被复制,而复制的析构函数刚刚使我的对象无效
不,那不是什么意思DynLibrary
有一个delete
d复制构造函数,因此如果通过重载解析以某种方式选择了该构造函数,则代码将不会编译
_handles.emplace(f, DynLibrary(f));
上面一行发生的事情是您正在创建一个临时的DynLibrary
对象,然后将其移动到无序映射中。如果希望避免此移动构造,请改用
现在,您直接在unordered_map
中构建DynLibrary
对象,并绕过临时对象的创建
作为T.C.,在这种情况下不需要分段构造构造函数,因为DynLibrary
有一个非显式的
转换构造函数。您可以通过以下操作实现与上述相同的效果:
_handles.emplace(f, f);
谢谢,那么std::分段_构造方法工作得很好。我仍然在想,为什么会有人想调用临时的析构函数?@Amxx:如果您拥有唯一的所有权资源,您应该使“移动自”对象不破坏其析构函数中的资源。@Amxx您构造了一个临时对象,然后将其用作无序映射中移动构造的源对象。一旦完成,临时的需要被销毁,不管它是否被移走。@Amxx Puppy在他的评论中有一个很好的观点。根据\u句柄
数据成员的类型,默认的移动构造函数可能不够。例如,如果它是一个void*
,您需要定义移动构造函数,并将源对象的\u句柄设置为nullptr
,以避免它在源对象的析构函数中被销毁。对于OP中显示的代码,您是否确实需要分段构建
?对(U1&&x,U2&&y)代码>构造函数应该处理它。(当然,如果DynLibrary(const std::string&path)
是显式的
,那么您需要它……)
_handles.emplace(std::piecewise_construct,
std::forward_as_tuple(f),
std::forward_as_tuple(f));
_handles.emplace(f, f);