Я сделал тест, используя этот код:
#include <iostream>
#include <unordered_set>
#include <unordered_map>
struct A
{
static int copies;
A(int a): a(a){}
A(A const& pA){std::cout << "A copy" << std::endl; ++copies; a = pA.a;}
A& operator=(A const& pA){std::cout << "= operator" << std::endl; a = pA.a; ++copies; return *this;}
int a;
bool operator==(A const& pA)const{return pA.a == a;}
bool operator!=(A const& pA)const{return pA.a != a;}
bool operator>(A const& pA)const{return pA.a > a;}
bool operator<(A const& pA)const{return pA.a < a;}
};
int A::copies = 0;
namespace std{
template<>
class hash<A>
{
public:
size_t operator()(A const& pA) const
{
return pA.a;
}
};
}
int main()
{
std::unordered_map<A, A> map;
std::unordered_set<A> set;
for(int i=0; i<1000000; ++i)
{
set.insert(A(i));
map.insert(std::pair<A, A>(A(i), A(i)));
}
std::cout << A::copies << std::endl;
return 0;
}
Конструктор копирования для набора вызывался 1 миллион раз - это означает, что каждый объект был скопирован только один раз (в набор). Для копирования карты конструктор вызывался 4 млн раз - 2 раза домашний объект (обратите внимание, что для карты требуется 2 объекта A на каждую вставку). Более того, когда я запускаю тест, в котором я вставляю только один объект (для i <1), копирование construcotr вызывается один раз для набора и 4 раза для карты. </p>
Выводы:
Кажется, что перекомпоновка и вставка объектов не перераспределяет объекты ни в unordered_set, ни в unordered_map. Я думаю, что это правда, потому что я не верю, что не было ни одной перефразировки для стольких вставок. Конструктор копирования вызывался один раз для множества (для копирования объекта в узел множества) - очевидно. Почему тогда copy construcotr вызывался 4 раза для каждого вызова вставки карты? Ключ карты - это объект A, а значение - это объект A. Объекты были созданы, затем скопированы в std :: pair (первые 2 копии), а затем pair был скопирован в карту (еще 2 копии) - я думаю, что так оно и есть.
Так что кажется, что объекты в неупорядоченной карте и множестве никогда не перераспределяются, поэтому указатели и ссылки остаются действительными, а итераторы, вероятно, нет - @Alok Save answer. Я сделал этот тест, потому что мне было интересно, перераспределяются ли ключи, когда происходит перефразировка. @Alok Save писал об элементах, но не о ключах (или я не правильно понял его ответ, а элемент означает значение и ключ).
Вопрос:
Стандарт говорит что-нибудь о ключах (если они не рассматриваются как элементы)?
PS:
Для теста я использовал g ++ 4.8.