unorder_set<T>:INSERT(T&):如果存在参数是否移动?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (74)

这个问题是关于C+11标准库中几个函数的规范,这些函数将它们的参数作为rvalue引用,但并不是在所有情况下都使用它们。一个例子是std::unordered_set<T>::insert(T&&)

很明显,此方法将使用T若不存在元素,则在容器中构造元素。但是,如果元素已经存在于容器中,会发生什么?我很确定没有理由在这种情况下改变对象。然而,我没有在C+11标准中找到任何支持我的主张的东西。

这里有一个例子来说明为什么这可能是有趣的。下面的代码从std:CIN中读取行,并删除重复行的第一次出现。

std::unordered_set<std::string> seen;
std::string line;
while (getline(std::cin, line)) {
    bool inserted = seen.insert(std::move(line)).second;
    if (!inserted) {
        /* Is it safe to use line here, i.e. can I assume that the
         * insert operation hasn't changed the string object, because 
         * the string already exists, so there is no need to consume it. */
        std::cout << line << '\n';
    }
}

显然,此示例适用于gcc 4.7。但我不确定,是否符合标准。

提问于
用户回答回答于

我在标准(17.4.6.9)中找到了这张便条:

*如果程序在将lvalue传递给库函数时将lvalue强制转换为xvalue(例如,通过使用参数调用函数)move(x)),该程序实际上是要求该函数将该值作为临时值处理。实现可以自由优化,如果参数是lvalue,则可能需要对混叠检查进行优化。

虽然它没有直接回答你的问题,但它确实表明,实际上已经将库函数的参数作为临时参数“给予”,因此,一旦调用了它的值,我就不会依赖它的值了。insert。据我所知,库实现将有权从参数中移动,即使它随后确定它不会将值保存在容器中。

用户回答回答于

给出的语义insert关于§23.2.5/表103中的无序关联容器,不要指定参数的移动构造函数是否为insert如果插入失败,则该措辞只讨论插入是否发生:

a_uniq.insert(t)返回:pair<iterator, bool>要求:如果t是一个非参数表达式,T为“可移动到X”,则为,T将被复制到X。效果:插入t当且仅当容器中没有与t。返回对的bool组件指示插入是否发生,迭代器组件指向与t

正如@NicolBolas在评论中所指出的,尽管如此,不可能实现emplace函数不构造T如果冲突项已经存在。

因此,以一种符合标准的方式获取您想要的语义的唯一方法是做一个find有条件的,有条件的insertemplace

所属标签

可能回答问题的人

  • Hanzo

    6 粉丝0 提问7 回答
  • Richel

    9 粉丝0 提问3 回答
  • 上云小秘书

    15 粉丝0 提问2 回答
  • 风华一代

    3 粉丝469 提问2 回答

扫码关注云+社区

领取腾讯云代金券