C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?

xml*_*lmx 32 c++ stl rvalue-reference language-lawyer pass-by-rvalue-reference

#include <set>
#include <string>
#include <cassert>

using namespace std::literals;

int main()
{
    auto coll = std::set{ "hello"s };
    auto s = "hello"s;
    coll.insert(std::move(s));
    assert("hello"s == s); // Always OK?
}
Run Code Online (Sandbox Code Playgroud)

C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?

Ser*_*eyA 26

明确明确的NO。Standard没有这种保证,这就是为什么try_emplace存在的原因。

请参阅注释:

与insert或emplace不同,如果不执行插入操作这些函数就不会从rvalue参数移出,这使得操作值仅为移动类型的映射(例如)变得容易 std::map<std::string, std::unique_ptr<foo>>。此外,与分别try_emplace 对待keyd和arguments_type的情况不同,与不同 emplace,要求参数构造a value_type(即a std::pair


And*_*dyG 8

没有。

尽管@NathanOliver指出,并且仅当没有等效键时,才会插入元素,但不能保证不会修改参数。

实际上,[map.modifiers]表示以下内容

template <class P>
pair<iterator, bool> insert(P&& x);
Run Code Online (Sandbox Code Playgroud)

相当于 return emplace(std::forward<P>(x)).

在哪里emplace可以完美地提出论点以构造另一个论点P,从而x保持某种有效但不确定的状态。

这是一个示例,该示例还演示(未证明)使用std::map(关联容器)时,值会稍微移动一点:

#include <iostream>
#include <utility>
#include <string>
#include <map>

struct my_class
{
    my_class() = default;
    my_class(my_class&& other)
    {
        std::cout << "move constructing my_class\n";
        val = other.val;
    }
    my_class(const my_class& other)
    {
        std::cout << "copy constructing my_class\n";
        val = other.val;
    }
    my_class& operator=(const my_class& other)
    {
        std::cout << "copy assigning my_class\n";
        val = other.val;
        return *this;
    }
    my_class& operator=(my_class& other)
    {
        std::cout << "move assigning my_class\n";
        val = other.val;
        return *this;
    }
    bool operator<(const my_class& other) const
    {
        return val < other.val;
    }
    int val = 0;
};

int main()
{
    std::map<my_class, int> my_map;
    my_class a;
    my_map[a] = 1;
    std::pair<my_class, int> b = std::make_pair(my_class{}, 2);
    my_map.insert(std::move(b)); // will print that the move ctor was called
}
Run Code Online (Sandbox Code Playgroud)