std::unorde...::operator=(3)
๐
std::unordered_multimap::operator= โ the C++ Standard Library glow-up, bestie โจ
okay so real talk, this one lives in the C++ Standard Library (cppreference.com vibes, we'll get to that at the end ๐) and it's the assignment operator for std::unordered_multimap. three overloads. three whole personalities. let's get into it ๐
๐ธ NAME ๐ธ
std::unordered_multimap::operator= โ literally the assignment operator for std::unordered_multimap, no notes ๐
โจ Synopsis โจ
okay so here's the whole menu, and yes there are three of them ๐ซถ
unordered_multimap& operator=( const (1) (since
unordered_multimap& other );
unordered_multimap& operator=( unordered_multimap&&
(since C++11)
other );
(until C++17)
unordered_multimap& operator=( unordered_multimap&& (2)
(since C++17)
other ) noexcept(/* see below */);
unordered_multimap& operator=( (3)
(since C++11)
std::initializer_list<value_type> ilist );
so clean it up in your head like this:
- (1) โ
unordered_multimap& operator=( const unordered_multimap& other );โ since C++11 - (2) โ
unordered_multimap& operator=( unordered_multimap&& other );โ since C++11, and until C++17 it looks exactly like that. from C++17 onward it'sunordered_multimap& operator=( unordered_multimap&& other ) noexcept(/* see below */); - (3) โ
unordered_multimap& operator=( std::initializer_list<value_type> ilist );โ since C++11
and what do they all do? replaces the contents of the container. that's the whole assignment vibe, periodt ๐ฅ
๐ the three overloads, explained like we're on facetime ๐
1) Copy assignment operator. it replaces the contents with a copy of the contents of other.
and here's the part where the allocator gremlins show up ๐ โ if std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value is true, then the allocator of *this gets replaced by a copy of other's allocator. and if the allocator of *this after assignment would compare unequal to its old value, then the old allocator is used to deallocate the memory, and then the new allocator is used to allocate it, and only then are the elements copied. otherwise? the memory owned by *this may just get reused when possible. and in any case, the elements originally belonging to *this may be either destroyed or replaced by element-wise copy-assignment. iykyk ๐
2) Move assignment operator. it replaces the contents with those of other using move semantics (i.e. the data in other is moved from other into this container). after that, other is in a valid but unspecified state โ so like, she's fine, but don't ask her questions ๐ญ
same allocator drama but move-flavoured: if std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value is true, the allocator of *this is replaced by a copy of that of other. but if it's false and the allocators of *this and other do not compare equal, then *this cannot take ownership of the memory owned by other and has to move-assign each element individually, allocating additional memory using its own allocator as needed ๐ซ and in any case, all elements originally belonging to *this are either destroyed or replaced by element-wise move-assignment. no shortcuts, no cap.
3) replaces the contents with those identified by initializer list ilist. short, sweet, iconic ๐
๐ฆ Parameters ๐ฆ
otherโ another container to use as data source ๐ilistโ initializer list to use as data source ๐ธ
โญ Return value โญ
*this
that's it. that's the return value. she returns herself, main character energy ๐
๐ Complexity ๐
- Linear in the size of
*thisandother. - Linear in the size of
*thisโ unless the allocators do not compare equal and do not propagate, in which case it's linear in the size of*thisandother. ๐ฎโ๐จ - Linear in the size of
*thisandilist.
๐ Exceptions ๐
until C++17:
1-3)May throw implementation-defined exceptions.
since C++17:
1,3)May throw implementation-defined exceptions.2)noexcept specification:
noexcept(std::allocator_traits<Allocator>::is_always_equal::value
&& std::is_nothrow_move_assignable<Hash>::value
&& std::is_nothrow_move_assignable<Pred>::value)
that noexcept clause is long, but she's worth it ๐ซถ
๐ Notes ๐
after container move assignment (overload (2)), unless element-wise move assignment is forced by incompatible allocators, references, pointers, and iterators (other than the end iterator) to other remain valid โ but they refer to elements that are now in *this. so they didn't die, they just moved in with you ๐
the current standard makes this guarantee via the blanket statement in [container.reqmts]/67, and a more direct guarantee is under consideration via LWG issue 2321. keep that in your back pocket for trivia night โจ
๐ง Example ๐ง
the following code uses operator= to assign one std::unordered_multimap to another:
// Run this code
#include <initializer_list>
#include <iostream>
#include <iterator>
#include <unordered_map>
#include <utility>
void print(auto const comment, auto const& container)
{
auto size = std::size(container);
std::cout << comment << "{ ";
for (auto const& [key, value] : container)
std::cout << '{' << key << ',' << value << (--size ? "}, " : "} ");
std::cout << "}\n";
}
int main()
{
std::unordered_multimap<int, int> x{{1,1}, {2,2}, {3,3}}, y, z;
const auto w = {std::pair<const int, int>{4,4}, {5,5}, {6,6}, {7,7}};
std::cout << "Initially:\n";
print("x = ", x);
print("y = ", y);
print("z = ", z);
std::cout << "Copy assignment copies data from x to y:\n";
y = x;
print("x = ", x);
print("y = ", y);
std::cout << "Move assignment moves data from x to z, modifying both x and z:\n";
z = std::move(x);
print("x = ", x);
print("z = ", z);
std::cout << "Assignment of initializer_list w to z:\n";
z = w;
print("w = ", w);
print("z = ", z);
}
๐ Possible output ๐
Initially:
x = { {3,3}, {2,2}, {1,1} }
y = { }
z = { }
Copy assignment copies data from x to y:
x = { {3,3}, {2,2}, {1,1} }
y = { {3,3}, {2,2}, {1,1} }
Move assignment moves data from x to z, modifying both x and z:
x = { }
z = { {3,3}, {2,2}, {1,1} }
Assignment of initializer_list w to z:
w = { {4,4}, {5,5}, {6,6}, {7,7} }
z = { {7,7}, {6,6}, {5,5}, {4,4} }
notice how the order is all over the place? that's an unordered multimap for you bestie, she does what she wants ๐ฆ (hence "possible output" โ don't come for me ๐)
๐ See also ๐
constructorโ constructs theunordered_multimap(public member function) โจ
๐ท๏ธ Category ๐ท๏ธ
- conditionally
noexcept
ok so that's the whole page!! copy it, move it, initializer-list it, live ur truth ๐
made with love, allocated with care, and yes the allocator propagated ๐ซถ
this little beauty came to you from http://cppreference.com, dated 2024.06.10, and it's page std::unorde...::operator=(3) of the C++ Standard Library docs โ go drink some water and then go assign something, mwah ๐
๐
๐ฆ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 ยท MIT
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms