c++ - unordered_map和emplace,为什么ctor被调用两次?

标签 c++ c++17

这里是一个示例代码:

struct T
{
    T(int x) : x_(x)
    {}

    T(T&&) = delete;
    T(const T&) = delete;

    int x_;
};

int main()
{
    std::unordered_map<int, T> m;
    m.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple(2));
    m.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple(2));

    return 0;
}

第二个 emplace 失败,但 T 构造函数被调用两次。我认为,只有当可以插入时, emplace 才会构造一个对象。你能解释一下吗?

编辑: 我使用 Visual Studio 2017 编译器。

最佳答案

来自cppreference :

The element may be constructed even if there already is an element with the key in the container, in which case the newly constructed element will be destroyed immediately.

出现这种行为的原因是容器需要构造一个关键对象才能检查它是否已经存在;映射对象必须同时构造,因为它们是同一对象(value_type 对)的成员。

try_emplace (C++17 起) 在这种情况下是更好的选择,因为它只会在插入成功时构造映射对象。它之所以能够做到这一点,是因为它将键作为第一个参数,并从其余参数中放置映射对象,从而产生更好的界面:

m.try_emplace(1, 2);
m.try_emplace(1, 2);
              ^ key (copied or moved)
                 ^ mapped_type emplacement args (forwarded)

关于c++ - unordered_map和emplace,为什么ctor被调用两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59934332/

相关文章:

c++ - 如何有效地将具有可变长度成员的对象保存到二进制文件中?

C++ 捕获移动初始化是 const 吗?

c++ - 在 Windows 中将文件所有者设置为不存在的用户/SID

c++ - 通过代码构造std::array并初始化元素对象

c++ - 为什么不能将 static constexpr 成员变量传递给函数?

c++ - 如何返回带有捕获的 unique_ptr 的 lambda

templates - 模板函数重载推导错误

python - Cython 中的引用资料

c++ - 出现在函数表达式中的变量是否通过引用获取参数但通过值 odr-used 返回?

c++ - 具有自动功能的 C++17 模板参数是否允许受约束的 std::function 对象?