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);