Возясь с итераторами с типизированными каламбурами, я наткнулся на возможность сделать
std::vector<int> vec{ 3, 7, 1, 8, 4 };
int* begin_i = (int*)(void*)&*vec.begin();
std::cout << "1st: " << begin_i << " = " << *begin_i << std::endl;
begin_i++;
std::cout << "2nd: " << begin_i << " = " << *begin_i << std::endl;
Затем я попытался сделать то же самое с std::unordered_set
:
std::unordered_set<int> set{ 3, 7, 1, 8, 4 };
for (auto& el : set)
{ // Display the order the set is currently in
std::cout << el << ", ";
}
std::cout << '\n' <<std::endl;
int* begin_i = (int*)(void*)&*set.begin();
std::cout << "1st: " << begin_i << " = " << *begin_i << std::endl;
begin_i++;
std::cout << "2nd: " << begin_i << " = " << *begin_i << std::endl;
Но результат, который я получил, был:
4, 8, 1, 7, 3,
1st: [address] = 4
2nd: [address] = 0
Я предполагаю, что это потому, что элементы неупорядоченного набора расположены в разных частях памяти? Я был сбит с толку, учитывая, что я также напечатал порядок, в котором элементы были сохранены, используя цикл на основе диапазона.
Мой вопрос: как std::unordered_set
хранит свои элементы в памяти? Что происходит, когда элемент добавляется в набор? Куда он попадает в памяти и как это отслеживается, если он не хранится в контейнере, похожем на массив, где элементы расположены один за другим?
std::unordered_*
состоит в том, чтобы использовать хеш-таблицу под капотом, что позволяет осуществлять поиск в постоянном времени. Таким образом, соответствующие итераторы должны иметь мозги, чтобы можно было найти следующий элемент; итератор дляstd::unordered_*
обычно не указатель. Когда вы делаете&*set.begin()
, вы вызываете пользовательскийoperator *
, который реализует интеллектуальный итератор, который дает указатель на элемент. Но следующий элемент может быть где угодно. - person cmaster - reinstate monica   schedule 12.12.2019