插入无序映射调用构造函数
Insert in unordered map calls constructor
为了避免元素重复,我正在构建一个 class 来保存元素并提供对它们的访问。
我的元素(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。 ,在这种情况下不需要分段构造构造函数,因为DynLibrary
有一个非explicit
转换构造函数。您可以使用
实现与上述相同的效果
_handles.emplace(f, f);
为了避免元素重复,我正在构建一个 class 来保存元素并提供对它们的访问。
我的元素(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。 DynLibrary
有一个非explicit
转换构造函数。您可以使用
_handles.emplace(f, f);