c++ - 插入无序映射调用构造函数

标签 c++ c++11 containers destructor rvalue

为了避免元素重复,我正在构建一个包含元素并提供对它们的访问的类。

我的元素 (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 有一个deleted 复制构造函数,因此如果通过重载解析以某种方式选择该构造函数,则代码将无法编译。

_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/

相关文章:

c++ - friend get 返回类型的函数,该函数通过可变参数模板递归计算

c++ - decltype 中的可变参数模板包

c++ - GCC 4.7 从初始化器列表初始化 unique_ptrs 容器失败

hyperlink - Docker链接容器

c++ - 非静态或常量数组语法

c++ - 如何将带有冒号的输入文件读入数组?

c++ - CUDA、互斥量和 atomicCAS()

c++ - cpp文件中函数的顺序

spring-boot - 带有生成器的gradle spring-boot 2.3.0.M3 buildpack --builder cloudfoundry/cnb:bionic cache jdk不会在每次运行时下载

c++ - 如何优雅地输入一组点