Does the C++ standard guarantee that a failed insertion into an associative container will not modify the rvalue-reference argument?

前端 未结 3 719
栀梦
栀梦 2020-12-30 20:22
#include 
#include 
#include 

using namespace std::literals;

int main()
{
    auto coll = std::set{ \"hello\"s };
    auto          


        
3条回答
  •  傲寒
    傲寒 (楼主)
    2020-12-30 20:46

    No.

    While @NathanOliver points out that an element will not be inserted if and only if there is no equivalent key, it does not guarantee that the arguments will not be modified.

    In fact, [map.modifiers] says the following

    template 
    pair insert(P&& x);
    

    equivalent to return emplace(std::forward

    (x)).

    Where emplace may perfectly forward the arguments to construct another P, leaving x in some valid but indeterminate state.

    Here's an example that also demonstrates (not proves) that with std::map (an associative container), a value gets moved around a bit:

    #include 
    #include 
    #include 
    #include 
    
    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_map;
        my_class a;
        my_map[a] = 1;
        std::pair b = std::make_pair(my_class{}, 2);
        my_map.insert(std::move(b)); // will print that the move ctor was called
    }
    
    • gcc (2 moves)
    • clang (1 move)

提交回复
热议问题